Конечный слеш в RESTful API

60

У меня были споры о том, что делать с косой чертой в RESTful API.

Допустим, у меня есть ресурс под названием собаки и подчиненные ресурсы для отдельных собак. Поэтому мы можем сделать следующее:

GET/PUT/POST/DELETE http://example.com/dogs
GET/PUT/POST/DELETE http://example.com/dogs/{id}

Но что нам делать со следующим частным случаем:

GET/PUT/POST/DELETE http://example.com/dogs/

Мое личное мнение таково, что это говорит о том, что нужно отправить запрос на ресурс отдельной собаки с id = null. Я думаю, что API должен вернуть 404 для этого случая.

Другие говорят, что запрос обращается к ресурсу собак, т.е. косая черта игнорируется.

Кто-нибудь знает окончательный ответ?

Gaz_Edge
источник
2
Я подумал, что RESTful способ провести различие между собакой / id и собаками (имеется в виду все собаки).
фунтовые
Из книги RESTful Web Services - подчиненные ресурсы: ресурсы, которые существуют по отношению к какому-либо другому «родительскому» ресурсу, например собакам / {id}. Веб-база данных с поддержкой веб-доступа может представлять таблицу как ресурс, а отдельные строки базы данных - как подчиненные ресурсы. ,
Gaz_Edge
Это доступ к ресурсу «собака», конечная косая черта должна игнорироваться, что означает, что он должен получить запрещенный ответ на попытку удаления чего-то, к чему не должно применяться удаление. Я думаю, что 404 также приемлемо. Это имеет значение, хотя?
Бенджамин Грюнбаум
Я не слежу - кто сказал, что вы не можете удалять собак? Если вы удаляете собак, он удаляет себя и всех отдельных собак. Вот почему я считаю, что разрешать звонки собакам / рискованно. Что, если клиент хотел удалить отдельную собаку, но случайно пропустил {id}. В результате все собаки будут удалены. Гораздо безопаснее предположить, что он запрашивает {id} null, и вернуть 404
Gaz_Edge
Я бы отнесся dogsи dogs/как эквивалент. Для меня понятно, что dogs/это каталог, содержащий отдельных собак. Менее понятно, что dogsесть, но я бы отнесся к этому как к эквивалентному, так же как большинство веб-серверов принимают доступ к каталогам без запаздывания /.
CodesInChaos

Ответы:

50

Ничто из этого не является авторитетным (поскольку REST не имеет точного значения). Но из оригинальной статьи о REST полный (не заканчивающийся на /) URL называет ресурс, в то время как один, заканчивающийся косой чертой '/', является группой ресурсов (вероятно, не так сформулировано).

GET URL с косой чертой в конце должен перечислять доступные ресурсы.

GET http://example.com/dogs/          /* List all the dogs resources */

PUT в URL с косой чертой должен заменить все ресурсы.

PUT http://example.com/dogs/          /* Replace all the dogs resources */

УДАЛЕНИЕ на URL с косой чертой должно удалить все ресурсы

DELETE http://example.com/dogs/       /* Deletes all the dogs resources */

Предполагается, что POST для URL с косой чертой создаст новый ресурс, а затем будет доступен. Чтобы быть совместимым, новый ресурс должен находиться в этом каталоге (хотя многие из архитектур RESTful обманывают здесь).

POST http://example.com/dogs/        /* Creates a new dogs resource (notice singular) */

и т.п.

Вики-страница на эту тему, кажется, хорошо объясняет это:

Смотрите пример https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services .

Мартин Йорк
источник
Это также соответствует обычной модели пути / URL, где каталоги часто пишутся с /
конечным
4
Так что же произойдет, если вы получите доступ к группе ресурсов без конечного числа /?
oberlies
1
@oberlies: это зависит от контекста. Здесь нет жестких и быстрых правил, только лучшие практики. В правиле всегда есть исключения, и это должно означать то, что вы ожидаете от него. В приведенном выше примере: GET http://example.com/dogsможет возвращать метаинформацию о собаках (не сам список, а метаинформацию о списке собак). Может быть, или, возможно, это ошибка.
Мартин Йорк,
1
As the last character within a URI’s path, a forward slash (/) adds no semantic value and may cause confusion. It’s better to drop them completely.Это не единственное место , где предлагают не использовать тренировочный слеш
Laiv
@Laiv Я не согласен с мнением. Но, пожалуйста, свяжите более авторитетную ссылку (это слабая ссылка).
Мартин Йорк,
17
Does anyone know the definitive answer?

Нет такого, поскольку нет официального документа о том, что требуется для того, чтобы услуга считалась RESTful.

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

Майк
источник
А как насчет DELETE example.com/dogs ?
Бенджамин Грюнбаум
Так как собаки являются родителями всех отдельных собак, удаление собак приведет к удалению всех отдельных собак и самого себя. Если вы этого не сделаете, ваша гипермедиа выйдет из
строя
@Gaz_Edge: в REST example.com/dogsресурс полностью независим от любого ресурса example.com/dogs/X. Таким образом, DELETE on example.com/dogsне должен удалять всех собак / * (хотя может, если это семантика). Но DELETE example.com/dogs/должен удалить всех собак / *.
Мартин Йорк
3
Я хотел бы еще раз сказать, что поскольку не существует определенного набора правил относительно того, что является RESTful, то, что происходит, когда вы удаляете / собак или / собак /, будет основано на том, чего вы ожидаете от пользователей вашего API. Возможно ли, что они на самом деле захотят удалить всех собак одним запросом? Если это так, то реализуйте это так, если нет, то дайте ответ 405 «Метод не разрешен».
Майк
1
Я знаю, что это старая ветка, но недавно я сам задавался вопросом об этом. Для чего это стоит, то OS X Bash оболочки лечит foo, foo/и foo////тождественно. Похоже, что в основном удаляются пустые сегменты пути. Таким образом, если вы используете тот же подход с вашим REST-сервисом dogsи будете dogs/ссылаться на то же самое.
Грег Браун
2

Два пути.

Способ 1

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

Просто рассмотрите «GET» в каталоге public_html с файлами.

Невозможно, когда hello.html является файлом:

/hello.html
/hello.html/youagain.html

Но возможно, когда hello.html является каталогом:

/hello.html/     (actually /hello.html/index.html)
/hello.html/youagain.html

Так что, если у «hello.html» могут быть дети, то всегда и всегда «/hello.html/» и «/hello.html/index.html» (или просто /hello.html/) - это список этих детей. ,

Способ 2

Быть умным".

$ find
.
./hello.html
./hello.html/index.html

Команда find не заботится о типе hello.html. Каталог или файл, кому какое дело, это название объекта. Когда мы пишем «cp youagain.html hello.html», cp может выяснить, как обращаться с hello.html. ср умный. Ваш веб-сервер тоже умен. У него есть библиотека обработки пути. У него есть маршрутизация. Он может определить и сказать вам, является ли имя объектом или каталогом. Он может перенаправить бла на бла / или даже просто подать одинаковый ответ обоим. Это потрясающе !!! путь. Так много технологий. Кто когда-либо хотел бы просто объединить строки пути, когда мы могли бы сделать все это ???

Сэмюэл Даниэльсон
источник