Соглашение REST URI - имя ресурса в единственном или множественном числе при его создании


529

Я новичок в REST, и я заметил, что в некоторых сервисах RESTful они используют разные URI ресурса для обновления / получения / удаления и создания. Такие как

  • Создать - используя / resources с методом POST (соблюдайте множественное число) в некоторых местах используя / resource (единственное число)
  • Обновление - использование / resource / 123 с методом PUT
  • Get - Использование / resource / 123 с методом GET

Я немного смущен этим соглашением об именах URI. Что мы должны использовать множественное число или единственное число для создания ресурса? Какими должны быть критерии при принятии решения?


9
Следуя этой теме, я собрал несколько примеров известных API REST в статье: inmensosofa.blogspot.com/2011/10/… .
jjmontes

3
Заключение, к которому я пришел после прочтения всех ответов ниже: всегда используйте единственное число, потому что (а) оно непротиворечиво, (б) оно напрямую сопоставляется с именами классов и таблиц в единственном числе, (в) некоторые существительные во множественном числе нерегулярны (непредсказуемы) в английском языке
Уилл Шеппард

Посмотрите этот ответ для ссылки на соглашения об именах таблиц в единственном числе, и есть еще одна статья, в которой упоминается именно эта проблема . Дилемма Rest API разработчика - спасибо @Sorter
Уилл Шеппард

Ответы:


281

Предпосылка использования /resourcesзаключается в том, что он представляет «все» ресурсы. Если вы сделаете это GET /resources, вы, скорее всего, вернете всю коллекцию. Размещая в /resources, вы добавляете в коллекцию.

Тем не менее, отдельные ресурсы доступны в / ресурс. Если вы сделаете a GET /resource, вы, скорее всего, ошибетесь, так как этот запрос не имеет никакого смысла, тогда как /resource/123имеет смысл.

Использование /resourceвместо /resourcesаналогично тому , как вы могли бы сделать это , если вы работали с, скажем, файловой системы и набора файлов и /resourceявляется «каталог» с отдельными 123, 456файлы в нем.

Ни один путь не является правильным или неправильным, иди с тем, что вам нравится больше всего.


55
Отличный ответ! Но «стандартные» каталоги в Windows имеют множественные имена. Как "Program Files", "Users", "Documents", "Videos" и т. Д. Также я встречал множественные имена в URL веб-сайтов гораздо чаще.
Дмитрий Гончар

50
Соглашение о де-факто в значительной степени большинство людей и API принимают во множественном числе. Идентификаторы указывают ОДИН ресурс ресурса автомобили / id
PositiveGuy

205
«Ни один путь не является правильным или неправильным, иди с тем, что вам нравится больше всего». Ах, знаменитая строка, которую я слышу так часто и устаю слышать от людей. Условные обозначения имеют значение, и СЛЕДУЕТ конструктивно обсуждать их в сообществе, именно здесь появляются лучшие решения и передовой опыт. Когда вы используете как множественное, так и единственное число для имен ресурсов в URI, это усложняет ваш код и API, потому что пользователь и код API должны учитывать это в маршрутах и ​​логике, чтобы различать одиночное и множественное, тогда как если вы просто придерживаетесь с множественным числом все время у вас нет проблем.
PositiveGuy

30
@ TomaszPluskiewicz Вы совершенно правы, что клиенты не заботятся. Как разработчики программного обеспечения мы должны заботиться - и для этого я согласен с замечанием WTF о том, что конструктивные дебаты по поводу соглашения являются ценными.
Трэвис Д

12
Поэтому кто-то может просто ответить одним словом и принять его, чтобы мне не пришлось читать все это (снова).
Бен Джордж

624

Для меня лучше иметь схему, которую можно сопоставить непосредственно с кодом (легко автоматизировать), главным образом потому, что код - это то, что будет на обоих концах.

GET  /orders          <---> orders 
POST /orders          <---> orders.push(data)
GET  /orders/1        <---> orders[1]
PUT  /orders/1        <---> orders[1] = data
GET  /orders/1/lines  <---> orders[1].lines
POST /orders/1/lines  <---> orders[1].lines.push(data) 

22
Сложность или легкость этого в том, что мы не уважаем HATEOS. Не должно иметь значения, множественное ли это число, единственное число или что-то еще. Вы должны уважать URI, отправленный с сервера, а не «наращивать» URI на клиенте. Тогда у вас есть 0 сопоставлений для вашего кода.
Ричард

7
@richard Клиент все еще должен сделать отображение. В HATEOS они должны были бы сопоставить имя, которое представляет отношение (rel) к конструкции URI. Rel, метод (глагол) и Content-Type затем составляют носитель ресурса. Это не исключает необходимости хорошего дизайна URI. Несмотря на то, что клиент может отдавать приоритет названию rel, разработчикам API по-прежнему нужен хороший читабельный стандарт для построения URI.

4
Это лучший ответ на мой взгляд. За исключением того, что я всегда предпочитал использовать Singular вместо множественного числа. User.getList (), User.getById, User.delete и т. Д.
Восточный Монах

3
Мне нравится простота. Преимущество картографирования заключается в том, что документацию и тесты на маршрутах невероятно легко писать.
Делос

5
Это имеет смысл для меня. Однако мы являемся магазином, ориентированным на базу данных, то есть мы генерируем код и сущности API из нашей схемы базы данных. И стандарты баз данных, как правило, защищают имена таблиц в единственном числе, поэтому мы идем с этим, но все еще придерживаемся той же логики, что и ответ.
Андре С. Андерсен,

274

Я не вижу смысла в этом, и я думаю, что это не лучший дизайн URI. Как пользователь службы RESTful, я бы ожидал, что ресурс списка будет иметь одно и то же имя, независимо от того, получу ли я доступ к списку или к конкретному ресурсу «в» списке. Вы должны использовать одни и те же идентификаторы, независимо от того, хотите ли вы использовать ресурс списка или конкретный ресурс.


69
На мой взгляд, это лучший ответ. Я ценю то, что разработчикам API нравится лингвистическая правильность изречения «получить ресурс # 123», но это создает дополнительные трудности при написании кода клиентов API и справочной документации. (GET / api / people vs. GET / api / person / 123? Euuuchh.) .... вместо того, чтобы думать об этом, как "получить ресурс # 123", сформулируйте это в своей голове как "получить из коллекции ресурсов, которые соответствует # 123 ".
Уоррен Румак

5
Различение множественных / единичных ресурсов связано не с лингвистической правильностью, а с масштабом. / employee / 12 читается как подмножество ресурса сотрудников с идентификатором «12» (это может означать что угодно, например, сохраненный поисковый запрос недавно уволенных сотрудников). Если бы вы прочитали вышеприведенное как сотрудник с идентификатором «12», как бы вы представили подмножество? Единственный вариант - сделать более сложные руды URI, отличающие коллекции, содержащие объекты от самих объектов (то есть единственное и множественное).
Эрик

9
Я думаю, что выбор / employee / 12 для представления поискового запроса недавно уволенных сотрудников (или любого другого подмножества) был бы плохим дизайном. Если вы хотите представлять подмножества любого вида, я предлагаю представить их как ресурсы (с собственными именами) самостоятельно.
Ян Дейнхард

3
Это не имеет ничего общего с понятностью для клиентов. Речь идет о разных вещах с разными URL. И возможность отвечать на все методы HTTP без конфликта. Вы можете иметь ресурс, который представляет собой набор элементов, и ресурс, который представляет сам элемент. Как ни крути ресурс коллекций может быть example.org/166316e2-e1 и один конкретный элемент в этой коллекции example.org/20d68348-ccc-001c4200de . Клиент не должен создавать URL-адреса (это, очевидно, не масштабируется, это не RESTful, и именно для этого предназначены типы отношений ссылок).
Эрик

4
Если вы не считаете произвольные URL-адреса красивыми, не стесняйтесь идентифицировать ресурс коллекции с именем во множественном числе и отдельный элемент с именем в единственном числе. Если вам не нравятся английские URL-адреса, и ваш естественный язык не поддерживает этот способ обозначения singualr / множественное число, используйте что-то другое, чтобы определить его на предпочитаемом вами языке, я полагаю, что все языки позволяют вам как-то различать '/ the-collection-of- Bla / 2321 'против' Bla / 61 'в письменном виде. И каждый из этих двух разных ресурсов представляет совершенно разные результаты при отправке GET / PUT / DELETE / POST / PATCH и других.
Эрик

77

множественное число

  • Все просто - все URL начинаются с одинакового префикса
  • Логический - orders/получает индекс списка заказов.
  • Стандарт - наиболее распространенный стандарт, за которым следует подавляющее большинство публичных и частных API.

Например:

GET /resources - возвращает список элементов ресурса

POST /resources - создает один или несколько элементов ресурса

PUT /resources - обновляет один или несколько элементов ресурса

PATCH /resources - частично обновляет один или несколько элементов ресурса

DELETE /resources - удаляет все элементы ресурса

И для отдельных ресурсов:

GET /resources/:id- возвращает конкретный элемент ресурса на основе :idпараметра

POST /resources/:id - создает один элемент ресурса с указанным идентификатором (требуется проверка)

PUT /resources/:id - обновляет определенный элемент ресурса

PATCH /resources/:id - частично обновляет определенный элемент ресурса

DELETE /resources/:id - удаляет определенный элемент ресурса

Для сторонников единственного числа, подумайте об этом так: вы бы попросили кого-то за orderи ожидали одну вещь или список вещей? Так почему вы ожидаете, что сервис вернет список вещей при вводе /order?


10
Singular : В случае, когда частью вашей системы является только один объект (0-1, существует или нет), например users / 1 / avatar, вы можете использовать форму единственного числа для обозначения этого единственного объекта (например, avatar) - более подробный пример здесь: stackoverflow .com / a / 38296217/860099 . Кстати, очень хороший ответ :)
Камиль Келчевски

Как насчет сопоставления имен классов и таблиц, которые должны быть единичными? (см. другой ответ )
Уилл Шеппард

@WillSheppard - Имена классов лучше всего в единственном числе, а имена таблиц лучше всего во множественном числе. Например, Orderхорошее имя для класса, который имеет дело с единичными экземплярами объектов, ссылающимися на один порядок. OrderListэто имя класса, который имеет дело с несколькими Orderэкземплярами. Orders Tableэто хорошее название для таблицы базы данных многих заказов.
Эрик Кнудтсон,

Я хочу получить / заказы, но я хочу только / 1
Джим Смит

@ jim-smith, почему бы вам не запросить / 1 из коллекции пользователей с GET / users / 1?
Ромер

49

Единственное число

удобство Вещи могут иметь неправильные имена во множественном числе. Иногда их нет. Но имена в единственном числе всегда есть.

например, CustomerAddress поверх CustomerAddresses

Рассмотрим этот связанный ресурс.

Это /order/12/orderdetail/12более читабельно и логично, чем/orders/12/orderdetails/4 .

Таблицы базы данных

Ресурс представляет сущность, подобную таблице базы данных. У него должно быть логическое единственное имя. Вот ответ по именам таблиц.

Отображение классов

Классы всегда единичны. Инструменты ORM генерируют таблицы с теми же именами, что и имена классов. По мере того, как все больше и больше инструментов используются, единичные имена становятся стандартом.

Узнайте больше о дилемме разработчика REST API


39
Необычные имена всегда есть /clothe/12/trouser/34 :)
Герт Арнольд

18
@GertArnold слово clotheэто глагол. API отдыха обычно придерживаются существительных, когда говорят о ресурсах, и используют глаголы при описании действий. Форма единственного числа есть clout, но она архаична и, вероятно, будет более подходящей заменой garment.
Стив Бузонас

@SteveBuzonas А для брюк и солнцезащитных очков?
Корай Тугай

32

В то время как наиболее распространенной практикой является API RESTful, где используется множественное число, например /api/resources/123, есть один особый случай, когда я нахожу использование единственного имени более подходящим / выразительным, чем множественное число. Это случай отношений один-к-одному. В частности, если целевой элемент является ценностным объектом (в парадигме управляемой доменом разработки).

Давайте предположим, что каждый ресурс имеет взаимно-однозначное отношение, accessLogкоторое может быть смоделировано как объект значения, т. Е. Не объект, следовательно, не ID. Это может быть выражено как /api/resources/123/accessLog. Обычные глаголы (POST, PUT, DELETE, GET) надлежащим образом выражают намерение, а также тот факт, что отношения действительно взаимно-однозначные.


4
Хорошая попытка. Но это было бы лучше как "accessLogEntries". :-)
Том Рассел

8
@ TomRussell почему? Последствия этого важны. Я понимаю, почему вы должны использовать множественное число, даже когда вы обращаетесь к ресурсу по идентификатору, но для многих один или один к одному это вводит в заблуждение. Рассмотрим API, который управляет сотрудниками в многопрофильной компании. Каждый сотрудник работает в одном месте. GET /users/123/locationдолжен выбрать местоположение, в котором работает пользователь. Разве это не GET /users/123/locationsобманчиво как потребитель?
Кэрри Кендалл

1
@CarrieKendall Я понимаю вашу точку зрения. Поскольку accessLogон моделируется как атрибут или значение, а не как сущность, он должен быть единственным. Если вы слишком перегружены, то в записи журнала будет сущность, и вы бы это сделали /api/accessLogEntries?resource=123.
Том Рассел

Согласен, хотя, я думаю, что это нарушает соглашение о множественности всех вещей. Это сложно. Для меня важно, чтобы API был простым, то есть документация должна дополнять уже прямую реализацию.
Кэрри Кендалл

Я больше программист, чем специалист по системам или базам данных, поэтому мне нравится API, который рассказывает историю, а не придерживается соглашения. Однако последствия для автоматизированной документации реальны.
Том Рассел

26

Почему бы не следовать распространенной тенденции имен таблиц базы данных, где единственная форма общепринятая? Был там, сделал это - давайте снова использовать.

Дилемма именования таблиц: единственные и множественные имена


8
Das Auto намного лучше, чем Die Autos. Кроме того, английские множественные соглашения не согласуются.
FlavorScape

7
Пространство имен ресурса - это вопрос семантики, а не реализации. Так что, используя аналогию с таблицами БД, не очень повезло. Также при работе с БД вы манипулируете только таблицами, хотя, конечно, вы можете влиять на содержимое (строки), но в REST нет ограничений на непосредственное управление одним ресурсом.
arpadf

3
Я думаю, что это хорошая аналогия, но она важнее того, чтобы решить, следует ли идти в единственном или множественном числе, чтобы соответствовать тому, что вы выберете. Вы не собираетесь вставлять в Пользователи, а затем выбрать из Пользователя. То же правило должно применяться к ресурсам REST - не переименовывайте их в зависимости от того, что вы делаете.
Тодд Менье

3
Это не только имена таблиц, но и сравнимые с именами классов в ОО (мой класс будет называться Клиент, а не Клиент).
bytedev

В этом случае семантика слишком важна, чтобы просто принимать «уже определенные» тенденции
Каттани Симоне

19

Я удивлен, увидев, что так много людей прыгнули бы на множественное число существительных побеждающих на выборах. При реализации преобразования единственного числа во множественное, вы заботитесь о нерегулярных существительных множественного числа? Вам нравится боль?

Видеть Http://web2.uvcs.uvic.ca/elc/studyzone/330/grammar/irrplu.htm.

Существует много типов нерегулярного множественного числа, но они являются наиболее распространенными:

Тип существительного Формирование множественного числа Пример

Ends with -fe   Change f to v then Add -s   
    knife   knives 
    life   lives 
    wife   wives
Ends with -f    Change f to v then Add -es  
    half   halves 
    wolf   wolves
    loaf   loaves
Ends with -o    Add -es 
    potato   potatoes
    tomato   tomatoes
    volcano   volcanoes
Ends with -us   Change -us to -i    
    cactus   cacti
    nucleus   nuclei
    focus   foci
Ends with -is   Change -is to -es   
    analysis   analyses
    crisis   crises
    thesis   theses
Ends with -on   Change -on to -a    
    phenomenon   phenomena
    criterion   criteria
ALL KINDS   Change the vowel or Change the word or Add a different ending   
     man   men
     foot   feet
     child   children
     person   people
     tooth   teeth
     mouse   mice
 Unchanging Singular and plural are the same    
     sheep deer fish (sometimes)

5
Я не понимаю проблемы здесь. Мы не должны изменять единственное число во множественное число программно. Большинство из вышеперечисленных форм множественного числа хорошо известны и не должны вызывать беспокойства. Если у кого-то плохое знание английского языка, он собирается написать любую часть вашей переменной неправильно. Кроме того, следуя вашей логике, вы также рекомендуете использовать формы единственного числа для ссылки на коллекции в исходном коде?
Кишор Борат

1
Есть английские слова, которые нерегулярны до такой степени, что это часто является проблемой даже в пределах англосферы, и они обычно используются такие термины, как индекс / индексы / индексы, вертикс / вершины / вершины, матрица / матрицы / матрицы, радиус / радиусы / радиусы и т. д. Я не вижу смысла делать множественные пути REST множественными, потому что, если они все последовательно единичны, это просто более очевидно для всех.
Черт

@kishorborate, использование множественного числа в качестве URI более подвержено ошибкам даже для носителей английского языка. Как указывает damd, множественное число, такое как index / indexes / indexes, создает больше проблем. И есть неисчислимые существительные. Смешивание неисчислимых существительных с множественным числом является еще одной проблемой. Зачем программистам труднее тратить на них больше времени? Я предлагаю использовать единственное число для всего. Если есть / {id}, то API должен вернуть одну запись. Если после него нет / {id}, API должен вернуть коллекцию.
Дами Фу

3
@DamingFu Единственный ресурс может не всегда иметь идентификатор, связанный с ним. например. / user / {id} / nickName Глядя на это, не ясно, вернется ли список nickNames или одного nickName? Следовательно, API более интуитивно понятны, когда используются формы множественного числа. Да, несколько слов будут иметь неправильные формы множественного числа. Для того, кто читает форму множественного числа, это не проблема. Это проблема только при написании подписи API. Но частота таких слов невелика, поэтому нахождение формы любого слова во множественном числе не занимает много времени. Мы должны согласиться с тем, чтобы сделать API более интуитивно понятными.
Кишор Борат

15

С точки зрения потребителя API конечные точки должны быть предсказуемыми, поэтому

Идеально...

  1. GET /resources должен вернуть список ресурсов.
  2. GET /resource должен вернуть код состояния 400 уровня.
  3. GET /resources/id/{resourceId} должен вернуть коллекцию с одним ресурсом.
  4. GET /resource/id/{resourceId} должен вернуть объект ресурса.
  5. POST /resources должен пакетно создавать ресурсы.
  6. POST /resource должен создать ресурс.
  7. PUT /resource должен обновить объект ресурса.
  8. PATCH /resource следует обновить ресурс, разместив только измененные атрибуты.
  9. PATCH /resources следует пакетно обновить ресурсы, публикуя только измененные атрибуты.
  10. DELETE /resourcesследует удалить все ресурсы; шучу: код статуса 400
  11. DELETE /resource/id/{resourceId}

Этот подход является наиболее гибким и многофункциональным, но он также требует больше времени для разработки. Так что, если вы спешите (что всегда имеет место при разработке программного обеспечения), просто назовите свою конечную точку resourceили форму множественного числа resources. Я предпочитаю единственную форму, потому что она дает вам возможность анализировать и оценивать программно, поскольку не все формы множественного числа заканчиваются на «s».

Сказав все это, по любой причине, которую выбрал наиболее часто используемый разработчик практики, это использовать форму множественного числа. Это в конечном итоге маршрут, который я выбрал, и если вы посмотрите на популярных API-интерфейсов, githubи twitterэто то, что они делают.

Некоторые критерии для принятия решения могут быть:

  1. Какие у меня временные ограничения?
  2. Какие операции я позволю своим потребителям делать?
  3. Как выглядит запрос и результат?
  4. Хочу ли я иметь возможность использовать отражение и анализировать URI в моем коде?

Так что решать вам. Просто будь последовательным.


1
Похоже, форма множественного числа была выбрана, потому что разработчики, кажется, предполагают, что все ресурсы являются неотъемлемой частью некоторой коллекции. Однако «принятое соглашение», похоже, указывает на то, что POST /usersследует создать одного пользователя, добавив его в коллекцию. Я не согласен. POST /usersдолжен создать список пользователей (даже если это список из 1), где as POST /userдолжен создать ровно один пользователь. Я не вижу причин, по которым как множественные, так и единичные конечные точки ресурса не могут сосуществовать. Они описывают различное поведение и не должны никого удивлять своей функцией.
раздавить

Существует ли соглашение для указания идентификатора ресурса в пути? Если так, то, похоже, им пренебрегают. Например, POST users/<id>создаст нового пользователя.
Том Рассел

1
@TomRussell обычно сервер создает идентификатор, поэтому вы еще не знаете идентификатор для POST.
Алекс

3
@TomRussell, когда клиент определяет (своего рода) идентификатор при создании нового ресурса, его чаще используют PUT /users/<id>вместо POST. POSTимеет интерпретацию «добавить это в коллекцию и определить идентификатор как часть этого». PUTимеет интерпретацию "обновить (или добавить) этот ресурс с этим идентификатором." См. Restcookbook.com/HTTP%20Methods/put-vs-post для более подробного объяснения этого принципа.
Йохем Шуленклоппер

Я не верю, что сравнение с Twitters API справедливо, поскольку они используют форму Plural для всех своих конечных точек. Они не смешивают множественное число и единственное число для одних и тех же элементов.
Эндрю Т Финнелл

7

Мои два цента: методы, которые проводят время, переходя от множественного числа к единственному или наоборот, - пустая трата циклов ЦП. Я могу быть старой школы, но в свое время такие вещи назывались одинаково. Как мне искать методы, касающиеся людей? Никакое регулярное выражение не покроет и человека и людей без нежелательных побочных эффектов.

Английские множественные числа могут быть очень произвольными, и они напрасно кодируют код. Придерживайтесь одного соглашения об именах. Компьютерные языки должны были быть с математической ясностью, а не с имитацией естественного языка.


2
Это адрес кода, который пытается «автоматически сгенерировать / манипулировать» конечными точками (есть много самоуверенных библиотек, которые предполагают множественность / особенность и пытаются отобразить); однако это применимо к явно выбранным именам конечных точек не больше, чем к выбору правильного слова (независимо от того, как оно используется во множественном числе).
user2864740

6

Я предпочитаю использовать единственную форму для простоты и последовательности.

Например, учитывая следующий URL:

/ Клиент / 1

Я буду относиться к клиенту как к коллекции клиентов, но для простоты часть коллекции удалена.

Другой пример:

/ Оборудование / 1

В этом случае оборудование не является правильной формой множественного числа. Таким образом, обработка его как сбора оборудования и удаление сбора для простоты делает его совместимым с делом клиента.


2
POST / customer звучит так, как будто он собирается заменить единственного клиента. Это мое самое большое горе с использованием уникальных имен ресурсов.
Эндрю Финнелл

2
@ andrew-t-finnell Разве не POST /customerнужно делать что-то одно - вставить одного клиента?
Donmutti

Он вставляет одного Клиента в коллекцию Клиентов. POST /customerчитает мне, как будто это POST'ing к theклиенту. Не коллекция клиентов. Тем не менее, я признаю, что Plural или нет Plural является предпочтением. Пока они не смешаны, как в другом ответе. Это было бы невероятно запутанным.
Эндрю Финнелл

«POST'ing to the customer» не имеет смысла в этом случае. POST не заменяет, он вставляет. Может быть, если бы это был POST / customer / 1, я мог бы увидеть дилемму, но даже это не имеет особого смысла с точки зрения REST, потому что вы вставляете? Это будет / клиент / 1 / счет или / клиент / 1 / квитанция и т. Д.
черт

5

Идентификатор в маршруте должен рассматриваться так же, как индекс для списка, и присвоение имен должно выполняться соответствующим образом.

numbers = [1, 2, 3]

numbers            GET /numbers
numbers[1]         GET /numbers/1
numbers.push(4)    POST /numbers
numbers[1] = 23    UPDATE /numbers/1

Но некоторые ресурсы не используют идентификаторы в своих маршрутах, потому что есть только один, или пользователь никогда не имеет доступа к более чем одному, поэтому это не списки:

GET /dashboard
DELETE /session
POST /login
GET /users/{:id}/profile
UPDATE /users/{:id}/profile

4

С соглашениями об именах, как правило, можно с уверенностью сказать «просто выберите один и придерживайтесь его», что имеет смысл.

Однако после объяснения REST многим людям представление конечных точек в виде путей в файловой системе является наиболее выразительным способом сделать это.
Он не имеет состояния (файлы существуют или не существуют), иерархичен, прост и знаком - вы уже знаете, как получить доступ к статическим файлам, локально или через http.

И в этом контексте лингвистические правила могут дать вам только следующее:

Каталог может содержать несколько файлов и / или подкаталогов, поэтому его имя должно быть во множественном числе.

И мне это нравится.
Хотя, с другой стороны, это ваш каталог, вы можете назвать его «a-resource-or-множественные ресурсы», если вы этого хотите. Это не очень важно.

Важно то, что если вы поместите файл с именем «123» в каталог с именем «resourceS» (в результате /resourceS/123), вы не сможете ожидать, что он будет доступен через /resource/123.

Не пытайтесь сделать его умнее, чем нужно - переход от множественного числа к единственному в зависимости от количества ресурсов, к которым вы в данный момент обращаетесь, может быть эстетически приятен для некоторых, но это неэффективно и не имеет смысла в иерархическая система.

Примечание: Технически, вы можете создавать «символические ссылки», чтобы к ним /resources/123также можно было получить доступ через /resource/123, но первое еще должно существовать!


3

Посмотрите на Google «s API Design Guide: Resource Names для других взять на себя называющие ресурсах.

Короче говоря:

  • Коллекции названы множественным числом.
  • Отдельные ресурсы именуются со строкой.
|--------------------------+---------------+-------------------+---------------+--------------|
| API Service Name         | Collection ID | Resource ID       | Collection ID | Resource ID  |
|--------------------------+---------------+-------------------+---------------+--------------|
| //mail.googleapis.com    | /users        | /name@example.com | /settings     | /customFrom  |
| //storage.googleapis.com | /buckets      | /bucket-id        | /objects      | /object-id   |
|--------------------------+---------------+-------------------+---------------+--------------|

Это стоит прочитать, если вы думаете об этом предмете.


2

Использование множественного числа для всех методов более практично, по крайней мере, в одном аспекте: если вы разрабатываете и тестируете ресурсный API с помощью Postman (или аналогичного инструмента), вам не нужно редактировать URI при переключении с GET на PUT на POST и т. Д. ,


1
Для меня это не аргумент, поскольку Postman предлагает коллекции, так что вы можете сохранить все ресурсы как разные элементы коллекции и проверить их по отдельности. Все, что вы делаете, это выбираете ресурс из коллекции, вам не нужно каждый раз редактировать параметры / методы / и т.д.
Wirone

1

Оба представления полезны. Я использовал единственное число для удобства довольно долгое время, перегиб может быть трудным. Мой опыт в разработке строго единичных API REST: разработчики, использующие конечную точку, не уверены в том, какой может быть форма результата. Теперь я предпочитаю использовать термин, который лучше всего описывает форму ответа.

Если все ваши ресурсы на высшем уровне, то вы можете сойтись с единичными представлениями. Избегать перегиба - большая победа.

Если вы выполняете какие-либо глубокие ссылки для представления запросов в отношениях, разработчикам, пишущим против вашего API, может помочь более строгое соглашение.

Мое соглашение заключается в том, что каждый уровень глубины в URI описывает взаимодействие с родительским ресурсом, а полный URI должен неявно описывать то, что извлекается.

Предположим, у нас есть следующая модель.

interface User {
    <string>id;
    <Friend[]>friends;
    <Manager>user;
}

interface Friend {
    <string>id;
    <User>user;
    ...<<friendship specific props>>
}

Если бы мне нужно было предоставить ресурс, который позволил бы клиенту получить менеджера конкретного друга конкретного пользователя, он мог бы выглядеть примерно так:

GET /users/{id}/friends/{friendId}/manager

Ниже приведены еще несколько примеров:

  • GET /users - перечислить пользовательские ресурсы в глобальной коллекции пользователей
  • POST /users - создать нового пользователя в глобальной коллекции пользователей
  • GET /users/{id} - извлечь конкретного пользователя из глобальной коллекции пользователей
  • GET /users/{id}/manager - получить менеджера конкретного пользователя
  • GET /users/{id}/friends - получить список друзей пользователя
  • GET /users/{id}/friends/{friendId} - получить конкретного друга пользователя
  • LINK /users/{id}/friends - добавить ассоциацию друзей к этому пользователю
  • UNLINK /users/{id}/friends - удалить ассоциацию друзей у этого пользователя

Обратите внимание, как каждый уровень отображается на родителя, на которого можно воздействовать. Использование разных родителей для одного и того же объекта нелогично. Извлечение ресурса в не GET /resource/123оставляет никаких указаний на то, что создание нового ресурса должно быть сделано вPOST /resources


1

Я знаю, что большинство людей принимают решение, использовать ли множественное число или единственное число. Проблема, которая не была рассмотрена здесь, заключается в том, что клиенту необходимо знать, какой из них вы используете, и они всегда могут ошибиться. Отсюда и моё предложение.

Как насчет обоих? И под этим я подразумеваю использовать единственное число для всего вашего API, а затем создавать маршруты для пересылки запросов, сделанных во множественном числе, в единственное число. Например:

GET  /resources     =     GET  /resource
GET  /resources/1   =     GET  /resource/1
POST /resources/1   =     POST /resource/1
...

Вы получаете картину. Никто не ошибается, прилагая минимальные усилия, и клиент всегда все сделает правильно.


1
Если вы делаете 302 перенаправления и ваш кеш хранит все дважды, значит, вы неправильно настроили кеш. Кэш не должен хранить 302 редиректа.
wynnset

2
Если ваш клиент всегда использует /resourcesи всегда перенаправлен /resource, вы сделали это неправильно. Если кто-то еще использует ваш API, он может либо использовать правильный URL-адрес напрямую, либо быть перенаправленным (что работает, но неправильно), и именно вы открыли неправильный путь.
Maaartinus

Не уверен, что вы имеете в виду «неправильно» - это очень субъективно. Это не совсем так, потому что это работает.
Wynnset

Это увеличивает стоимость обслуживания, стоимость понимания и объем требуемого кода.
Уилл Шеппард

1

Мне не нравится, когда {id}часть URL-адресов пересекается с подресурсами, какid теоретически может быть что угодно, и возникнет неоднозначность. Он смешивает разные понятия (идентификаторы и имена подресурсов).

Подобные вопросы часто рассматриваются в enumпостоянных или папки структур, где разные понятия смешиваются (например, когда у вас есть папки Tigers, Lionsи Cheetahs, а затем также папка Animalsна том же уровне - это не имеет никакого смысла , так как один является подмножеством Другой).

В общем, я думаю, что последняя именованная часть конечной точки должна быть единственной, если она имеет дело с одной сущностью за раз, и множественной, если она имеет дело со списком сущностей.

Итак, конечные точки, которые имеют дело с одним пользователем:

GET  /user             -> Not allowed, 400
GET  /user/{id}        -> Returns user with given id
POST /user             -> Creates a new user
PUT  /user/{id}        -> Updates user with given id
DELETE /user/{id}      -> Deletes user with given id

Тогда есть отдельный ресурс для выполнения запросов к пользователям, которые обычно возвращают список:

GET /users             -> Lists all users, optionally filtered by way of parameters
GET /users/new?since=x -> Gets all users that are new since a specific time
GET /users/top?max=x   -> Gets top X active users

А вот несколько примеров подресурса, который имеет дело с конкретным пользователем:

GET /user/{id}/friends -> Returns a list of friends of given user

Завести друга (многие ко многим):

PUT /user/{id}/friend/{id}     -> Befriends two users
DELETE /user/{id}/friend/{id}  -> Unfriends two users
GET /user/{id}/friend/{id}     -> Gets status of friendship between two users

Не существует никакой двусмысленности, и множественное или единственное именование ресурса является подсказкой пользователю, чего он может ожидать (список или объект). Нет никаких ограничений на ids, теоретически позволяющих иметь пользователя с идентификатором newбез наложения на (потенциальное будущее) имя подресурса.


1

Используйте Singular и пользуйтесь английским соглашением, например, в «Business Directory».

Многие вещи читают таким образом: «Книжный шкаф», «Собачья стая», «Художественная галерея», «Кинофестиваль», «Автомобильный лот» и т. Д.

Это удобно соответствует пути URL слева направо. Тип элемента слева. Установите тип справа.

GET /usersДействительно ли когда-нибудь выбирают группу пользователей? Как правило, не. Он выбирает набор заглушек, содержащих ключ и, возможно, имя пользователя. Так что это не совсем /usersтак. Это индекс пользователей, или «пользовательский индекс», если хотите. Почему бы не назвать это так? Это /user/index. Так как мы назвали тип набора, у нас может быть несколько типов, показывающих различные проекции пользователя, не прибегая к параметрам запроса, например, user/phone-listили /user/mailing-list.

А как насчет пользователя 300? Это все еще /user/300.

GET /user/index
GET /user/{id}

POST /user
PUT /user/{id}

DELETE /user/{id}

В заключение, HTTP может иметь только один ответ на один запрос. Путь всегда относится к чему-то единственному.


-1

Для меня множественное число манипулирует коллекцией , тогда как единственное число манипулирует предметом внутри этой коллекции.

Сбор позволяет методами GET / POST / DELETE

Пункт позволяет методы GET / PUT / DELETE

Например

POST on / ученики добавят нового ученика в школу.

УДАЛИТЬ на / ученики удалят всех учеников в школе.

DELETE on / student / 123 удалит ученика 123 из школы.

Это может показаться неважным, но некоторые инженеры иногда забывают идентификатор. Если маршрут всегда был множественным и выполнял УДАЛЕНИЕ, вы можете случайно стереть ваши данные. При отсутствии идентификатора в единственном числе будет возвращен маршрут 404, который не был найден.

Для дальнейшего расширения примера, если API должен был выставить несколько школ, то что-то вроде

DELETE on / school / abc / Students удалит всех учеников в школе abc.

Выбор правильного слова иногда является проблемой сам по себе, но мне нравится поддерживать множественность для коллекции. Например, cart_itemsили cart/itemsчувствует себя хорошо. В отличие от удаления cart, удаляет объект корзины сам, а не элементы в корзине;).


Разве это не должно быть разделено на / cart и / cart / item (s)? Тогда вы можете обратиться ко всей корзине (например, с удалением) или отдельных предметов?
Роб Грант

@RobertGrant Разве это не будет "/ carts / items / 123"? (например, почему «тележка», а не «тележка» - это правило «всегда во множественном числе»?)
user2864740

1
Я бы сказал, что если проверен производственный код, способный выполнить удаление всех элементов корзины, возникают более серьезные проблемы, чем соглашение об именах. Вероятный капот, который они запомнят над идентификатором, гораздо меньше.
Эндрю Финнелл

Кто-нибудь когда-нибудь создать конечную точку, которая просто удаляет всю коллекцию? Мне кажется это чрезвычайно опасным, и, вероятно, также, почему REST не поддерживает пакетное удаление. (вам нужно будет обернуть массив в объект). Если бы мне абсолютно требовалась конечная точка для удаления всей коллекции, я бы удостоверился, что URI был очень очень уникальным и определенно не похож на POST
cnps

-1

Как насчет:

/resource/(нет /resource)

/resource/ означает, что эта папка содержит нечто, называемое «ресурс», это папка «resouce».

Кроме того, я думаю, что соглашение об именах таблиц базы данных такое же, например, таблица с именем «user» является «таблицей пользователя», она содержит нечто, называемое «user».


-2

Я предпочитаю использовать как множественное ( /resources), так и единственное ( /resource/{id}), потому что я думаю, что это более четко разделяет логику между работой над набором ресурсов и работой над одним ресурсом.

Важным побочным эффектом этого является предотвращение неправильного использования API. Например, рассмотрим случай, когда пользователь ошибочно пытается получить ресурс, указав Id в качестве параметра, например так:

GET /resources?Id=123

В этом случае, когда мы используем множественную версию, сервер, скорее всего, проигнорирует параметр Id и вернет список всех ресурсов. Если пользователь неосторожен, он подумает, что вызов прошел успешно, и воспользуется первым ресурсом в списке.

С другой стороны, при использовании единственного числа:

GET /resource?Id=123

сервер, скорее всего, вернет ошибку, потому что идентификатор не указан правильно, и пользователь должен будет понять, что что-то не так.


1
Почему вы смешиваете здесь идиомы? Вы используете правильную нотацию URI в первом абзаце, а затем переключаетесь на параметры запроса? Использование параметров запроса для получения ресурса с идентификатором 123 здесь совершенно не основано.
Эндрю Финнелл

Это было явно ошибкой. Я обновил свой ответ сейчас. Спасибо, что заметили это.
pberggreen

После того, как меня снова опровергли, я посмотрел на то, что написал, и понял, что исходное сообщение было правильным. Моя точка зрения заключалась в том, что если пользователь делает неправильные вещи, то использование множественного числа + единственного числа на самом деле даст лучшее сообщение об ошибке, чем использование множественного числа.
pberggreen

Я все еще чувствую, что это запутывает проблему под рукой. Идея использования множественного числа заключается в том, что это коллекция. И число на конце является указателем в коллекции. Что делать, если вы получаете / ресурс самостоятельно? Использование как множественного, так и единственного числа вместе довольно запутанно. Поговорка / resources / 123 говорит: «Получите мой ресурс 123 в корзину ресурсов».
Эндрю Т Финнелл
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.