Как создать REST URL без глаголов? - PullRequest
276 голосов
/ 25 октября 2009

Я изо всех сил пытаюсь определить, как создать спокойные URL-адреса. Я полностью за спокойный подход использования URL с существительными, а не глаголами, не понимаю, как это сделать.

Мы создаем сервис для реализации финансового калькулятора. Калькулятор принимает несколько параметров, которые мы будем загружать через файл CSV. Варианты использования будут включать:

  1. Загрузить новые параметры
  2. Получить последние параметры
  3. Получить параметры для данной бизнес-даты
  4. Сделать набор параметров активным
  5. Проверка набора параметров

Я полагаю, что спокойный подход будет иметь следующие типы URL:

/parameters
/parameters/12-23-2009

Первые три варианта использования можно выполнить с помощью:

  1. POST, куда вы включаете файл параметров в запрос поста
  2. GET первого URL
  3. GET второго URL

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

/parameters/ID/activate
/parameters/ID/validate

??

Ответы [ 8 ]

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

Общие принципы хорошего дизайна URI:

  • Не использовать параметры запроса для изменения состояния
  • Не используйте смешанные пути, если вы можете помочь; строчные буквы лучше
  • Не не использовать специфичные для реализации расширения в ваших URI (.php, .py, .pl и т. Д.)
  • Не попадать в RPC с вашими URI
  • Do максимально ограничить пространство URI
  • Do держать сегменты пути короткими
  • Do предпочитают либо /resource, либо /resource/; создать 301 перенаправления из того, который вы не используете
  • Do использовать параметры запроса для подбора ресурса; то есть нумерация страниц, поисковые запросы
  • Do переместить материал из URI, который должен быть в заголовке HTTP или теле

(Примечание: я не сказал "RESTful URI design"; URI по существу непрозрачны в REST.)

Общие принципы выбора метода HTTP:

  • Никогда никогда не используйте GET для изменения состояния; это отличный способ, чтобы робот Google испортил вам день
  • Не использовать PUT, если вы не обновляете весь ресурс
  • Не не используйте PUT, если только вы не можете на законных основаниях сделать GET для того же URI
  • Не использовать POST для извлечения информации, которая является долгоживущей или которая может быть разумной для кэширования
  • Не выполнять операцию, которая не является идемпотентной с PUT
  • Do использовать GET как можно больше
  • Do использовать POST вместо PUT, если сомневаешься
  • Делайте используйте POST всякий раз, когда вам нужно сделать что-то похожее на RPC
  • Do использовать PUT для классов ресурсов, больших или иерархических
  • Do использовать DELETE вместо POST для удаления ресурсов
  • Do использовать GET для таких вещей, как вычисления, если только ваш ввод не велик, в этом случае используйте POST

Общие принципы проектирования веб-сервисов с HTTP:

  • Не помещать метаданные в тело ответа, который должен быть в заголовке
  • Не помещать метаданные в отдельный ресурс, если только это не приведет к значительным издержкам
  • Do используйте соответствующий код состояния
    • 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-подобное" руководство выше. Для # 5, помните, что POST не обязательно должен использовать Content-Type: application/x-www-form-urlencoded. Это также может быть полезная нагрузка JSON или CSV.

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

Возможно что-то вроде:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }
18 голосов
/ 25 октября 2009

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

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

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

Что именно представляет «параметр»? Вероятно, множество разных вещей, каждая из которых должна иметь отдельный ресурс, выделенный для этого.

Еще один способ добиться этого - когда вы обсуждаете свое приложение с конечными пользователями (теми, кто, вероятно, мало что знает о программировании), какие слова они часто используют?

Это те слова, вокруг которых вы должны разрабатывать свое приложение.

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

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

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

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

Дизайн ваших URL не имеет никакого отношения к тому, является ли ваше приложение RESTful или нет. поэтому фраза "RESTful URLS" - это нонсенс.

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

Тем не менее, давайте перейдем к вашему вопросу: последние два случая не являются RESTful и не вписываются в какую-либо схему отдыха. Это то, что вы могли бы назвать RPC. Если вы серьезно относитесь к REST, вам придется заново продумать, как ваше приложение работает с нуля. Либо так, либо откажитесь от REST и просто сделайте свое приложение как приложение RPC.

Хммм, может быть, нет.

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

get [parametersurl] / validationresults

post [paramatersurl]

body: {команда: "активировать"}

но опять же, эта активирующая вещь - RPC, а не REST.

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

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

например. Создайте некоторые ресурсы, такие как,

/ActiveParameters
/ValidatedParameters

Если вы хотите сделать набор параметров активным, добавьте этот набор в коллекцию ActiveParameters. Вы можете передать набор параметров в виде тела объекта или передать URL-адрес в качестве параметра запроса следующим образом:

POST /ActiveParameters?parameter=/Parameters/{Id}

То же самое можно сделать с / ValidatedParameters. Если параметры недопустимы, сервер может вернуть «Bad Request» в запрос на добавление параметров в коллекцию проверенных параметров.

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

Я бы предложил следующий мета-ресурс и методы.

Сделать параметры активными и / или проверить их:

> 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': '...'}
< }
<
0 голосов
/ 25 октября 2009

В среде REST каждый URL является уникальным ресурсом. Каковы ваши ресурсы? Финансовый калькулятор действительно не имеет никаких очевидных ресурсов. Вам нужно покопаться в том, что вы называете параметрами, и вытащить ресурсы. Например, календарь погашения кредита может быть ресурсом. URL-адрес календаря может включать начальную дату, срок (в месяцах или годах), период (когда начисляются проценты), процентную ставку и начальный принцип. Со всеми этими значениями у вас есть определенный календарь платежей:

http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000

Теперь я не знаю, что вы рассчитываете, но ваша концепция списка параметров не звучит RESTful. Как кто-то еще сказал, ваши требования звучат более XMLRPC. Если вы ищете REST, вам нужны существительные. Вычисления - это не существительные, а глаголы, которые действуют на существительные. Вам нужно перевернуть его, чтобы вытащить существительные из ваших слов.

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

Редактировать: Действительно, URI не позволил бы GET запросам оставаться идемпотентными.


Однако для проверки использование кодов состояния HTTP для уведомления о действительности запроса (для создания нового или изменения существующего «параметра») соответствовало бы модели Restful.

Сообщите с кодом состояния 400 Bad Request, если переданные данные являются / недействительными и запрос должен быть изменен перед повторной отправкой ( HTTP / 1.1 Коды состояния ).

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

...