Restful URL с данными в строке запроса или теле запроса? - PullRequest
33 голосов
/ 25 октября 2009

Какое практическое правило для передачи данных в URL-адресе REST в строке запроса относительно тела запроса?

Т.е .: вы создаете сервис для добавления хоккеистов. Вы можете пойти с:

PUT /players 
{ "name": Gretzky }

или

PUT /players?name=Gretzky

Если вы передаете много данных, вам нужно использовать опцию № 1, поскольку существует ограничение на длину URL. Но кроме этого, почему бы просто не использовать строку запроса для передачи данных?


Обновление : удален комментарий, который вы можете проверить в браузере для опции №2. Понял (дух), что вы можете делать только GET-ы в вашем браузере.

Ответы [ 4 ]

31 голосов
/ 25 октября 2009

Основываясь на определении HTTP PUT, ваш первый запрос переписывает список игроков новым списком, который содержит только одно имя игрока. Это не добавление в список игроков.

Второй вариант не имеет особого смысла для меня. Выполнение PUT без тела на самом деле не соответствует значению PUT.

Учитывая, что одним из стандартных определений POST является добавление к существующему ресурсу, я не уверен, почему вы не сделали бы

POST /players 
{ "name": Gretzky }

Если вы уверены, что все имена ваших игроков будут уникальными, вы можете использовать PUT следующим образом:

PUT /player/Gretzky
{ "name": Gretzky }

Когда вы решите выполнить REST по HTTP, вы соглашаетесь использовать HTTP способом, определенным в RFC2616. Вот что означает унифицированное ограничение интерфейса. И просто для того, чтобы быть педантичным, не существует такого понятия, как REST URL, и вы не можете проверить ни один из вариантов в браузере, потому что без JavaScript вы не можете сделать PUT в браузере.

3 голосов
/ 25 октября 2009

Вариант № 1 в порядке, хотя, вероятно, излишний. Вариант № 1 не в порядке, поскольку он не идемпотентен.

Вариант № 2 - это идея BAD . Это было бы неправильно использовать PUT. PUT следует использовать в первую очередь, когда полезная нагрузка запрашиваемых данных представляет собой непрозрачный блок данных, обычно большой или иерархический. Меньшие, неиерархические полезные нагрузки имеют больше смысла как POST.

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

В этом случае вам следует сделать следующее:

POST /players HTTP/1.1
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

name=Gretsky

Это должно вернуть 201 Created ответ. (Существует исключение из этого: если вы не создаете ресурс сразу, и он может быть отклонен позднее, используйте вместо него 202 Accepted.)

Написание веб-службы REST, использующей больше HTTP, чем POST и GET, следует выполнять только после , прочитав HTTP-спецификацию . (Это очень полезное чтение.) Это правило немного более утомительно, если вы используете платформу, которая принимает все решения за вас.

2 голосов
/ 25 октября 2009

Мое понимание операций REST состоит в том, что URL-адрес уникально идентифицирует ресурс, а тело запроса содержит представление ресурса. Учитывая это, сомнительно, действительно ли любой из ваших вариантов действительно RESTful.

Первым будет предположить, что ресурс называется «Players», а GET на этом ресурсе возвращает список игроков (я не буду задавать вопрос о том, возвращает ли этот GET URL других ресурсов или нет ... Филдинг сказал бы, что должен, с отдельными запросами на получение данных ресурса).

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

0 голосов
/ 25 октября 2009

Используемый URL должен идентифицировать ресурс в теле, либо по компонентам пути, либо по параметрам запроса, хотя я бы предпочел компоненты пути для чего-то вроде имени или идентификатора. Тело должно быть представлением; тот, который вы ставите, должен быть таким же или похожим на тот, который вы получаете по одному и тому же URL (или можете получить в случае нескольких форматов)

Пример № 1 неуместен, поскольку вы отправляете представление для одного игрока на URL-адрес всех игроков. POST будет более уместным в этом случае.

Пример №2 будет несколько неуместным, если он будет распространен на все поля, потому что тогда вы будете отправлять данные представления в URL.

...