Как создать REST URL-адреса без глаголов?
-
06-07-2019 - |
Вопрос
Я изо всех сил пытаюсь определить, как создавать restful URL-адреса.Я полностью за restful-подход использования URL-адресов с существительными, а не глаголами, но не понимаю, как это сделать.
Мы создаем сервис для внедрения финансового калькулятора.Калькулятор принимает множество параметров, которые мы загрузим через CSV-файл.Варианты использования будут включать:
- Загрузить новые параметры
- Получите последние параметры
- Получение параметров для заданной деловой даты
- Сделайте набор параметров активным
- Проверка набора параметров
Я полагаю, что подход restful состоял бы в том, чтобы иметь URL-адреса следующего типа:
/parameters
/parameters/12-23-2009
Вы могли бы реализовать первые три варианта использования с помощью:
- ОПУБЛИКУЙТЕ, где вы включаете файл параметров в запрос post
- ПОЛУЧЕНИЕ первого URL-адреса
- ПОЛУЧЕНИЕ второго URL-адреса
Но как вы выполняете 4-й и 5-й варианты использования без глагола?Разве вам не нужны такие URL-адреса, как:
/parameters/ID/activate
/parameters/ID/validate
??
Решение
Возможно, что-то вроде:
PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18
{ "active": true }
Другие советы
Общие принципы хорошего проектирования URI:
- Не надо используйте параметры запроса для изменения состояния
- Не надо используйте пути со смешанным регистром, если вы можете помочь этому;лучше всего использовать нижний регистр
- Не надо используйте расширения, зависящие от реализации, в ваших URI (.php, .py, .pl и т.д.)
- Не надо впасть в RPC с вашими URI
- Делай максимально ограничьте пространство вашего URI
- Делай держите сегменты пути короткими
- Делай предпочитаю либо
/resource
или/resource/
;создайте 301 перенаправление с того, который вы не используете - Делай используйте параметры запроса для дополнительного выбора ресурса;т. е.разбивка на страницы, поисковые запросы
- Делай удалите из URI данные, которые должны быть в HTTP-заголовке или теле
(Примечание:Я не говорил "RESTful URI design".;URI по существу непрозрачны в REST.)
Общие принципы выбора метода HTTP:
- Не надо вы когда-нибудь использовали GET для изменения состояния;это отличный способ заставить робота Googlebot испортить вам день
- Не надо используйте PUT, если только вы не обновляете весь ресурс целиком
- Не надо используйте PUT, если вы также не можете законно выполнить GET для того же URI
- Не надо используйте POST для извлечения информации, которая является долговременной или которую может быть разумно кэшировать
- Не надо выполните операцию, которая не идемпотентный с помощью PUT
- Делай используйте GET как можно чаще
- Делай используйте POST в качестве предпочтения для РАЗМЕЩЕНИЯ, когда сомневаетесь
- Делай используйте POST всякий раз, когда вам нужно сделать что-то, похожее на RPC
- Делай используйте PUT для классов ресурсов, которые являются более крупными или иерархическими
- Делай используйте "УДАЛИТЬ" вместо "ОПУБЛИКОВАТЬ", чтобы удалить ресурсы
- Делай используйте GET для таких вещей, как вычисления, если только ваши входные данные не велики, в этом случае используйте POST
Общие принципы проектирования веб-сервиса с использованием HTTP:
- Не надо поместите метаданные в тело ответа, которые должны быть в заголовке
- Не надо поместите метаданные в отдельный ресурс, если только их включение не приведет к значительным накладным расходам
- Делай используйте соответствующий код состояния
201 Created
после создания ресурса;ресурс должен существует на момент отправки ответа202 Accepted
после успешного выполнения операции или асинхронного создания ресурса400 Bad Request
когда кто-то выполняет операцию с данными, которые явно поддельны;для вашего приложения это может быть ошибкой проверки;обычно резервируйте 500 для неперехваченных исключений401 Unauthorized
когда кто-то обращается к вашему API либо без предоставления необходимогоAuthorization
заголовок или когда учетные данные вAuthorization
являются недействительными;не используйте этот код ответа, если вы не ожидаете учетных данных черезAuthorization
заголовок.403 Forbidden
когда кто-то получает доступ к вашему API способом, который может быть вредоносным, или если он не авторизован405 Method Not Allowed
когда кто-то использует POST, когда он должен был использовать PUT и т. Д413 Request Entity Too Large
когда кто-то пытается отправить вам файл недопустимо большого размера418 I'm a teapot
при попытке заварить кофе с помощью чайника
- Делай используйте заголовки кэширования всякий раз, когда вы можете
ETag
заголовки хороши, когда вы можете легко свести ресурс к хэш-значениюLast-Modified
должен указать вам, что сохранение метки времени обновления ресурсов является хорошей идеейCache-Control
иExpires
должны быть даны разумные значения
- Делай все, что вы можете для соблюдения кэширования заголовков в запросе (
If-None-Modified
,If-Modified-Since
) - Делай используйте перенаправления, когда они имеют смысл, но для веб-службы они должны быть редкими
Что касается вашего конкретного вопроса, POST следует использовать для #4 и #5.Эти операции подпадают под приведенное выше руководство "RPC-like".Для # 5 помните, что POST не обязательно должен использовать Content-Type: application/x-www-form-urlencoded
.С таким же успехом это может быть полезная нагрузка в формате JSON или CSV.
Всякий раз, когда кажется, что вам нужен новый глагол, подумайте о том, чтобы превратить этот глагол в существительное.Например, превратите "активировать" в "активация", а "проверка" в "валидация".
Но только из того, что вы написали, я бы сказал, что у вашего приложения гораздо большие проблемы.
Каждый раз, когда предлагается ресурс под названием "параметр", он должен вызывать красные флажки в сознании каждого члена проектной команды.'параметр' может применяться буквально к любому ресурсу;это недостаточно конкретно.
Что именно представляет собой "параметр"?Вероятно, это несколько разных вещей, каждой из которых должен быть посвящен отдельный ресурс.
Другой способ добиться этого - когда вы обсуждаете свое приложение с конечными пользователями (теми, кто предположительно мало разбирается в программировании), какие слова они сами используют неоднократно?
Это те слова, на основе которых вы должны разрабатывать свое приложение.
Если вы еще не провели это преобразование с потенциальными пользователями - остановите все прямо сейчас и не пишите больше ни строчки кода, пока не сделаете этого!Только тогда у вашей команды будет представление о том, что нужно построить.
Я ничего не знаю о финансовом программном обеспечении, но если бы мне пришлось гадать, я бы сказал, что некоторые ресурсы могут иметь такие названия, как "Отчет", "Платеж", "Перевод" и "Валюта".
Существует ряд хороших книг по этой части процесса разработки программного обеспечения.Два, которые я могу порекомендовать, это Дизайн, ориентированный на предметную область и Шаблоны анализа.
Дизайн ваших URL-адресов не имеет никакого отношения к тому, является ли ваше приложение RESTful или нет.таким образом, фраза "RESTful URLS" является бессмыслицей.
Я думаю, вам следует еще немного почитать о том, что такое REST на самом деле.REST рассматривает URL-адреса как непрозрачные и поэтому не знает, что в них содержится, будь то глаголы, существительные или что-то еще.Возможно, вы все еще захотите создать свои URL-адреса, но это касается пользовательского интерфейса, а не REST.
Тем не менее, давайте перейдем к вашему вопросу:Последние два случая не являются RESTful и не вписываются ни в какую схему restful.Это то, что вы могли бы назвать RPC.Если вы серьезно относитесь к REST, вам придется переосмыслить, как работает ваше приложение с нуля.Либо так, либо откажитесь от REST и просто делайте свое приложение как RPC-приложение.
Хммм, может, и нет.
Идея здесь в том, что вы должны относиться ко всему как к ресурсу, поэтому, как только у набора параметров есть URL, по которому вы можете ссылаться на него, вы просто добавляете
получить [parametersurl]/validationresults результаты проверки
сообщение [paramatersurl]
Тело:{команда:"активировать"}
но опять же, эта активирующая штука - RPC, а не REST.
Требования к активации и проверке - это ситуации, когда вы пытаетесь изменить состояние ресурса.Это ничем не отличается от того, что оформление заказа "завершено" или какой-либо другой запрос "отправлен".Существует множество способов моделирования такого рода изменений состояния, но один, который, как я нахожу, часто работает, - это создать ресурсы коллекции для ресурсов одного и того же состояния, а затем перемещать ресурс между коллекциями, чтобы повлиять на состояние.
например ,Создайте некоторые ресурсы, такие как,
/ActiveParameters
/ValidatedParameters
Если вы хотите сделать набор параметров активным, добавьте этот набор в коллекцию ActiveParameters.Вы могли бы либо передать набор параметров как тело объекта, либо вы могли бы передать URL-адрес в качестве параметра запроса следующим образом:
POST /ActiveParameters?parameter=/Parameters/{Id}
То же самое можно сделать с параметром /ValidatedParameters .Если параметры недопустимы, то сервер может вернуть "Неверный запрос" на запрос о добавлении параметров в коллекцию проверенных параметров.
Я бы предложил следующий мета-ресурс и методы.
Сделайте параметры активными и / или подтвердите их:
> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<
Проверьте, являются ли параметры активными и действительными:
> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
< 'active': true,
< 'require-valid': true,
< 'valid': {'status': false, 'reason': '...'}
< }
<
В среде REST каждый URL-адрес является уникальным ресурсом.Каковы ваши ресурсы?Финансовый калькулятор на самом деле не располагает какими-либо очевидными ресурсами.Вам нужно покопаться в том, какие параметры вы вызываете, и извлечь ресурсы.Например, ресурсом может быть календарь погашения кредита.URL-адрес календаря может включать start_date, term (в месяцах или годах), period (когда начисляются проценты), процентную ставку и начальный принцип.Со всеми этими значениями у вас есть определенный календарь платежей:
http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000
Теперь, я не знаю, что вы вычисляете, но ваша концепция списка параметров не звучит успокаивающе.Как сказал кто-то другой, ваши требования выше звучат скорее как XMLRPC.Если вы пытаетесь ОТДОХНУТЬ, вам нужны существительные.Вычисления - это не существительные, это глаголы, которые воздействуют на существительные.Вам нужно перевернуть его, чтобы вытащить существительные из ваших вычислений.
Редактировать: Действительно, URI предотвратил бы GET
запросы от оставшегося идемпотента.
Однако для проверки использование кодов состояния HTTP для уведомления о действительности запроса (для создания нового или изменения существующего "параметра") соответствовало бы модели Restful.
Отчитайтесь с помощью 400 Bad Request
код состояния, если отправленные данные являются недействительными и запрос должен быть изменен перед повторной отправкой (Коды состояния HTTP/1.1).
Однако это зависит от проверки во время отправки, а не от ее отсрочки, как в вашем случае использования.В других ответах есть подходящие решения для этого сценария.