Должен ли ответ RESTful GET возвращать идентификатор ресурса?

Некоторые разработчики ведут дружеское (некоторые сказали бы, религиозное) обсуждение вопроса о том, должен ли запрос GET от RESTful API возвращать идентификатор запрошенного ресурс. Предположим, следующий запрос GET:

http://my.api.com/rest/users/23

В настоящее время возвращается:

{"name": "Jim", "age": 40, "favoriteColor": "blue"}

Обратите внимание, что «id» отсутствует в наборе результатов.

По сути, с этой проблемой борются четыре лагеря.

ЛАГЕРЬ №1: когда вызывающие абоненты отправляют запрос GET, они уже знают идентификатор. Таким образом, набор результатов не должен содержать идентификатор. Если вызывающим абонентам нужны эти данные для включения редактирования пользовательского интерфейса, тогда вызывающим абонентам необходимо передать идентификатор 23, возможно, вручную добавив член {"id": 23} в JSON.
Люди из лагеря № 1 также утверждают, что наличие идентификатор в результирующем наборе будет указывать на то, что это значение можно изменить, чего, конечно же, нельзя.

ЛАГЕРЬ №2: без идентификатора набор результатов JSON не может использоваться изначально для операций редактирования / обновления в формах пользовательского интерфейса. Вместо этого механизм обратного вызова AJAX должен отвечать за передачу полей идентификатора и ручное добавление их в набор результатов. Это кажется странным и подверженным ошибкам. Специалисты по пользовательскому интерфейсу утверждают, что в результирующем наборе "ощущается" отсутствие данных, которые должны присутствовать, а именно идентификатора.

ЛАГЕРЬ №3: Эти люди озабочены единообразием. Если у нас когда-либо будет коллекция пользовательских объектов, возвращаемых API, эти объекты ДОЛЖНЫ включать идентификатор. Следовательно, для согласованности одноэлементная версия GET также должна включать идентификатор.

ЛАГЕРЬ №4: эти люди предполагают, что запрос GET для пользователя может возвращать метаданные в форме HyperMedia или SelfLinks, которые будут включать идентификатор.

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


person Armchair Bronco    schedule 02.07.2012    source источник
comment
Это личное мнение, но я согласен с лагерями 2 и 3. Я думаю, что представление должно содержать все доступные данные, включая ID. Особенно когда это натуральный идентификатор. Это очень интересный вопрос, но я сомневаюсь, что вы найдете простой ответ.   -  person toniedzwiedz    schedule 03.07.2012
comment
С точки зрения клиента URI, используемый в GET - это идентификатор. Я бы проголосовал за Camp 4, предполагая, что идентификатор, используемый в ссылке self, представляет собой весь URI, а не только часть в конце.   -  person Brian Kelly    schedule 03.07.2012
comment
Люди в лагере 4 с облегчением увидят, что они не одни. И для подтверждения, если бы они включили идентификатор, он был бы встроен в полный URI. Это означает, что необходимо будет проанализировать URI для извлечения идентификатора, но, по крайней мере, для людей из лагеря 2 им не нужно вручную изменять полезную нагрузку JSON. С другой стороны, сторонники Camp 1 утверждают, что такой URI будет лишь частичной реализацией REST Level 3, поэтому по этой причине им не нравятся встроенные SelfLinks.   -  person Armchair Bronco    schedule 03.07.2012


Ответы (2)


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

Вы возвращаете представление состояния объекта или ресурса. Идентификатор является частью этого представления и, следовательно, должен быть включен в пакет JSON. Это свойство ресурса. Независимо от того, знает ли звонящий идентификатор или нет, не имеет особого отношения к обсуждению. ЛАГЕРЬ №1 стоит на шаткой почве.

То, что вы говорите о коллекциях, очень актуально. Имеет ли смысл использовать одно представление для операции retrieve-1 и другое представление для операции retrieve-N? Думаю, нет.

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

Все достаточно зрелые протоколы REST имеют возможность формировать возвращаемые данные.

Примеры см.


Facebook позволяет вам явно указывать нужные поля.

введите описание изображения здесь

API stackexchange интересен. Они определили совершенно новый тип объекта для поддержки формы. Вы можете использовать API, чтобы определить «фильтр» и сохранить его на стороне сервера. Затем в своем запросе вы передаете параметр фильтра с идентификатором фильтра, и возвращаемые представления объекта включают все атрибуты, указанные в фильтре. Без фильтра вы получаете подмножество полей "по умолчанию". Чтобы получить «все поля», вам нужно определить всеобъемлющий фильтр.

вы можете увидеть это в действии на странице https://api.stackexchange.com/docs/answers.

... и, в частности, смотрите диалог спецификации фильтра.

введите описание изображения здесь


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

person Cheeso    schedule 02.07.2012
comment
Спасибо за вдумчивый и подробный ответ. Я долго и упорно думал о том, чтобы задать этот вопрос из-за опасений, которые вы выразили в первом предложении: это вопрос вашего мнения, а не тот вопрос, который любит видеть Stackoverflow. Как получатель страшного значка «Давление со стороны сверстников», я слишком хорошо знаю, что может случиться с вопросом, основанным исключительно на мнении. На мой взгляд, однако, эта проблема имеет столько программных последствий для различных лагерей, что я решил рискнуть. - person Armchair Bronco; 03.07.2012
comment
Со своей стороны, я сделал все возможное, чтобы сделать Лагерь №1 счастливым. Теперь я передаю массив пар ключ / значение, который я могу использовать для увеличения или дополнения данных, возвращаемых вызовами на основе AJAX к службам RESTful. Это работает, но кажется неправильным. Ребята из лагеря №1 согласились добавить идентификатор, если я и другие потребители API действительно хотят, чтобы эти данные были частью ответа полезной нагрузки GET. - person Armchair Bronco; 03.07.2012
comment
Позвольте мне спросить вас: что, если запросом является не получение человека с ID = N, а получение автора документа с DOCID = Z? Если вы последуете совету из Лагеря №1, вы получите объект-человек, но вы не знаете его ID. Позиция лагеря №1 кажется очень узкой и несостоятельной. Не имеет смысла, за исключением самых простых и непрактичных сценариев. - person Cheeso; 03.07.2012
comment
Я передам ваш комментарий. Как главный участник Лагеря №2, я нахожусь не в том Лагере, чтобы ответить на ваш законный вопрос. :-) - person Armchair Bronco; 03.07.2012
comment
Просто принял это как ответ. На мой взгляд, лагеря 2 и 3 имеют наибольший смысл. Как уже отмечалось, в настоящее время я прохожу идентификатор вручную, а затем добавляю его в JSON в своих функциях обратного вызова. Тотальный хакфест, если вы спросите меня. Идентификатор является неотъемлемой частью запрошенного мной объекта, поэтому он должен возвращаться вместе с полезными данными независимо от того, знаю я идентификатор или нет. И нет смысла возвращать разные поля для вызовов GET-1 и GET-N. Спасибо всем за отзывы. - person Armchair Bronco; 06.07.2012
comment
Это не совсем субъективный вопрос. REST имеет определение, придуманное человеком (Роем Филдингом), придумавшим этот термин. - person Mark E. Haase; 26.02.2015

Старый вопрос, но раз уж я попал сюда в поисках чего-то, вот еще одно мнение:

Прежде всего, я думаю, что URL-адрес должен быть:

http://my.api.com/rest/Users/23

нет

http://my.api.com/rest/getUsers/23

«GET» относится к методу HTTP, а не к URL-адресу. Это просто наименование, но помогает прояснить ситуацию, ИМХО.

Если вы думаете об этом, изменение ресурса должно произойти в том же URL-адресе с PUT

ПОСТАВИТЬ http://my.api.com/rest/Users/23

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

Если вы попытаетесь ПОЛУЧИТЬ восстановление на другой URL, скажите «http://my.api.com/rest/Users/24 ", может произойти несколько сценариев:

1) http://my.api.com/rest/Users/24 уже существует на сервере и сервер принимает ресурс как обновление

2) http://my.api.com/rest/Users/24 не существуют на сервере и:

a) сервер принимает, что пользователь предоставляет идентификатор (24) несуществующему ресурсу (не рекомендуется) b) сервер принимает PUT как POST

В a + b сервер создаст новый ресурс.

So:

1) В зависимости от того, насколько вы доверяете своему клиенту, вам, вероятно, следует создать на сервере элемент управления «регистрация / выписка», чтобы избежать перезаписи одного ресурса другим (это RESTful?)

2) Вы не должны принимать клиентов, создающих идентификаторы (ОК, чтобы опубликовать http://my.api.com/rest/Users/, а не http://my.api.com/rest/Users/24), и вам не следует принимать PUT для несуществующих ресурсов.

ИЗМЕНИТЬ:

Поэтому я считаю, что ресурс идентифицируется по URL-адресу, а не по идентификатору. Или, другими словами, идентификатор ресурса - http://my.api.com/rest/Users/23, а не 23.

Имеет смысл?

person noderman    schedule 07.02.2014
comment
Я согласен с тем, что вставлять get в URI было ошибкой. Я посмотрю, смогу ли я изменить OP. Спасибо за ответ. - person Armchair Bronco; 07.02.2014
comment
Поэтому я считаю, что ресурс идентифицируется по URL-адресу, а не по идентификатору. Это суть ответа. Ваш клиент не должен создавать URL-адреса, поэтому, если идентификатор не используется для какой-либо другой цели, вам не нужно включать его в ответ ... никогда. Даже в коллекции. Если вы хотите, чтобы клиент знал, где найти отдельный ресурс, укажите URL вместо идентификатора. См. HATEOAS. - person Mark E. Haase; 26.02.2015