Какой HTTP-глагол мне следует использовать для запуска действия в веб-службе REST?

81

Я внедряю веб-сервис RESTful, и одно из доступных действий будет reload. Он будет использоваться для перезагрузки конфигураций, кеша и т. Д.

Мы начали с простого GETURI, подобного этому: ${path}/cache/reload(параметры не передаются, вызывается только URI). Я знаю, что данные не должны быть изменены с помощью запроса GET.

Какой правильный глагол использовать для вызова действия / команды в веб-службе RESTful?

Перезагрузка - это команда веб-службы REST, которая перезагружает свой собственный кэш / конфигурацию / и т. Д. Это не метод, который возвращает информацию клиенту.

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

Я нашел этот подробный вопрос о переполнении стека на эту тему: https://stackoverflow.com/questions/16877968/

Ренато Динхани
источник
1
«Перезагрузка» - это смысл приложения, обновляющего данные, которые оно собирается отобразить? Есть ли разница между перезагрузкой и получением данных снова?
Шон Редмонд
1
@SeanRedmond Нет, данные не отправляются клиенту. Фактически, клиент говорит веб-службе REST выполнить и внутреннюю команду (перезагрузить). Что-то вроде: «в базе данных было изменено много конфигураций, поэтому веб-сервис REST, перезагрузите их в свою память сейчас».
Ренато Динхани
Межсайтовый дубликат: stackoverflow.com/q/15340946/319403
cHao
Рассматривали ли вы использование параметра заголовка в соответствующих запросах? Это звучит очень похоже на обновление кэша ...
Гуран

Ответы:

25

Я не думаю, что есть правильный глагол для этого действия, потому что эта транзакция на самом деле не "RESTful". «S» и «t» означают «передача состояния», и здесь ничего не передается. Или, другими словами, по самому строгому определению, глаголы типа PUT и POST всегда используются с существительным, а у «перезагрузки» просто есть глагол.

Эта перезагрузка может быть не RESTful, но она все равно может быть полезна, и вам нужно будет просто выбрать способ сделать это и жить с ней или объяснить, что это необычно. GET, наверное, самый простой. Тем не менее, в комментариях довольно много скептицизма, поэтому вы должны подумать о том, требуется ли это действие перезагрузки, потому что что-то еще не совсем делает то, что должно.

Шон Редмонд
источник
Я согласен, что это не RESTful, но может быть полезно. Я думаю, что вы должны посоветовать PUT, потому что это, вероятно, идемпотент, но не нульимпотент.
Аарон Гринвальд
@ Аарон, сравнение идемпотента и нульимпотента все хорошо, но как ты определяешь, когда оно неимпотентно?
Крейг
@ Крэйг, он идемпотентен, если многократный запуск его приводит к тому же результату, что и запуск его один раз. Это нульпотентно, если запуск его один или несколько раз имеет тот же эффект на сервере, что и запуск его ноль раз. en.wikipedia.org/wiki/Idempotence
Аарон Гринвальд
5
@AaronGreenwald «notimpotent» [not-im-poht-nt] [not-im-pawr-tnt] - прилагательное - 1. Игра слов, «не важно», антоним прилагательного «важно». 2. Юмор… ;-)
Крейг,
@Craig Я полностью пропустил это :)
Аарон Гринвальд
75

Если вы хотите быть RESTful, не думайте о глаголе для выполнения действия, думайте о состоянии, в котором вы хотите, чтобы ресурс находился после того, как клиент что-то сделал.

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

Таким образом, клиент помещает новое состояние на сервер для этого ресурса. Это может быть так просто, как этот JSON

PUT http://myserver.com/services/email_service HTTP/1.1
Content-Type: text/json

{"status":"paused"}

Сервер выясняет, как перейти от текущего состояния (скажем, «работает») к «приостановленному» состоянию / состоянию.

Если клиент выполняет GET для ресурса, он должен вернуть состояние, в котором он находится в данный момент (скажем, «приостановлен»).

Причина, по которой вы делаете это таким образом, и почему REST может быть настолько мощным, заключается в том, что вы оставляете КАК добраться до этого состояния на сервере.

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

Таким образом, вы можете полностью переписать / изменить дизайн сервера, а клиенту все равно. Клиент должен знать только о различных состояниях (и их представлениях) ресурса, а не о каких-либо внутренних элементах.

Кормак Мулхолл
источник
2
Насколько я понимаю, это правильный ответ. Обновление данных на сервере не является идемпотентной операцией и GETсовершенно не подходит для использования. PUTявляется наиболее подходящим глаголом, поскольку операция может рассматриваться как обновление «перезагрузки состояния» кэша до «перезагрузки».
Jez
@Jez Из ответов здесь я предпочитаю и этот. Вставлять с электронной метафорой, навскидку это действительно чувствует странное на первом думать отправки почты, поместив его в «отправке» государство вместо того , чтобы просто отправив его (действие). Но если вы думаете об этом, это действительно то же самое, что положить его в «исходящие». Фактически, сама почтовая система, вероятно, помещает ее в очередь таким образом, когда вы указываете ее на отправку. Таким образом, API может позволить вам перевести почту в состояние «отправка», и API не обязан объясняться выше этого.
Крейг
Таким образом, если вы не хотите, чтобы сообщение отправлялось, вы переводите его в «запланированное» состояние с указанием даты / времени, когда оно должно быть выпущено. Если он не завершен, вы помещаете его (или это неявно / по умолчанию) в состояние «черновик» и т. Д.
Крейг,
... хотя я думаю, что в этом случае я бы предпочел POST вместо PUT, поскольку предполагается, что PUT также является идемпотентом, но POST не имеет таких ограничений.
Крейг
1
Вы можете сделать это, но в конечном итоге он пытается вставить квадратный колышек в круглое отверстие. Нет никаких причин, по которым клиент должен запускать сервер для «перезагрузки» чего-либо, это просто плохой архитектурный дизайн. Сервер может обновлять свое внутреннее состояние при каждом вызове или через фиксированный интервал времени. Доверие клиента к тому, что он скажет серверу перезагружать что-либо независимо от любого фактического запроса состояния ресурса, не является архитектурой RESTful.
Кормак Мулхолл
32

Некоторые другие ответы, включая принятый, советуют вам использовать GET (хотя и не с большим энтузиазмом).

Я не согласен.

Во-первых, все остальные, говорящие вам, что это не идеально и не совсем RESTful, верны. В правильном сценарии RESTful вы управляете ресурсами на сервере и добавляете, обновляете, удаляете, извлекаете и т. Д. Эти ресурсы. PUT должен отправлять полезную нагрузку, которая представляет собой ресурс, который должен быть, когда запрос завершен, а POST должен отправлять полезную нагрузку, которая представляет ресурс, который должен быть добавлен на сервер. И GET должен вернуть ресурс на сервере.

У вас есть RPC (удаленный вызов процедуры), который не является RESTful - вы хотите что-то сделать на сервере. Поэтому, если вы пытаетесь создать чисто RESTful API, вам следует пересмотреть то, что вы делаете.

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

Если вы это сделаете, я бы порекомендовал PUT или POST, в зависимости от того, является ли RPC идемпотентом или нет.

В общем, мы говорим, что HTTP PUT отображается на SQL UPDATE, а HTTP POST отображается на SQL INSERT, но это не совсем так. Более чистый способ заявить, что HTTP PUT должен быть идемпотентным, а HTTP POST не обязательным. Это означает, что вы можете вызывать один и тот же запрос PUT столько раз, сколько захотите, без побочных эффектов. Как только вы назвали это один раз, это безопасно, чтобы позвонить снова. Но вам не следует повторно вызывать POST-запросы, если вы не хотите - каждый POST снова изменяет данные на сервере.

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

Аарон Гринвальд
источник
6

POSTи PUTHTTP-глаголы, используемые для отправки объекта на веб-сервер. С PUT, представленная сущность является (новым) представлением для ресурса в данном URI, который не соответствует тому, что вы хотите. POSTдля традиционного обработчика форм, где сущность является вспомогательными данными для ресурса, так что это победитель. Объект должен включать команду или действие (например, «действие = перезагрузка»).

Тем не менее, рассматриваемая команда, вероятно, не должна быть представлена ​​через интерфейс REST. Похоже, что необходимость в «перезагрузке» возникает потому, что данные могут быть изменены через какой-то другой канал (например, файловая система, клиент БД). Кеши должны быть прозрачными. Более того, HTTP-запросы должны быть атомарными, даже принимая во внимание сообщения, отправленные по другим каналам. Предложение команды «перезагрузить» для параметров конфигурации кажется ненужной сложностью; требуя это хрупкий дизайн. Использование «перезагрузки» для очистки после обновления через другой канал является грязным, поскольку один канал не содержит весь диалог. Вместо этого рассмотрим одно из:

  • делать обновления полностью через REST
  • подвергая команду (и) другому каналу
  • автоматизация действий

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

Смотрите также " PUT vs POST in REST ".

outis
источник
Спасибо. Я удалил «внутреннее» редактирование, потому что на самом деле метод «перезагрузки» предназначен для публичного использования. Я просто хотел сказать, что это относится к самому веб-сервису. Я думаю, что размещение "действий" было бы хорошим подходом.
Ренато Динхани
@ RenatoDinhaniConceição: даже без «внутреннего», он все еще пахнет. Возможно, вам следует задать новый вопрос о том, является ли дизайн хорошим.
outis
4

Я бы поспорил, почему клиентский запрос явно должен был бы сделать вызов, чтобы обновить что-то подобное. Похоже, это должно быть либо скрытой логикой в ​​более типичной реализации GET (т. Е. Извлечение данных, но служба выполняет обновление данных перед их извлечением), либо с помощью другого триггера в бэкэнде вдали от клиента.

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

Томас Стрингер
источник
Посмотри на мои правки. «reload» - это не команда, которая возвращает данные. Это относится к самому веб-сервису REST. В общих чертах мой вопрос касается запуска действий в веб-сервисе REST. Другой пример может быть: email_queue/stop_sending_emails. Я просто даю команду чему-то, используя интерфейс RESTful.
Ренато Динхани
5
Я все еще согласен. Вызывать SIGHUP для локального процесса имеет смысл, поскольку компьютер должен доверять кому-то, кто вошел в систему локально и имеет доступ к этому сигналу. Но для протокола без доступа к Интернету? Возможно, веб-сервис должен автоматически перезагружаться при необходимости через опрос или мониторинг файлов. Этот вызов должен быть совершенно ненужным.
1
Я согласен. Такие вещи, как конфигурация и кэширование, должны быть прозрачными для клиента. Возможно, вам следует дать нам более конкретное описание ситуации, в которой будет называться ваша конечная точка.
Бенджамин Ходжсон
3

Почему бы не относиться к действию как к ресурсу. Таким образом, поскольку вы хотите обновить кэш, вы должны ЗАПИСАТЬ новое действие в вашей системе.

Для пуристов у вас могут быть специальные URL для этого. Обратите внимание, что вы можете расширить это и записать фактические действия в базе данных (или в любом другом хранилище) с указанием даты, статуса, пользователя и т. Д. Просто мои мысли здесь

Типовая общесистемная операция / действия / {действие}

Операция, специфичная для типа ресурса / actions / {resource} / {action}

Операция, относящаяся к ресурсу / actions / {resource} / {id} / {action}

В вашем случае кеш, вероятно, общесистемный / actions / reload_cache

Isometriq
источник
0

Какой HTTP-глагол мне следует использовать для запуска действия в веб-службе REST?

При рассмотрении деталей службы REST часто бывает полезно рассмотреть эту эвристику: как бы вы реализовали это на веб-сайте?

HTML может только описывать запросы GET и POST. Таким образом, мы можем начать поиск там.

Является ли GETуместно? Чтобы ответить на этот вопрос, нам нужно подумать о допущениях, которые могут делать клиенты и промежуточные компоненты GET. Семантика GETявляются безопасными

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

Следовательно, это означает, что клиенты и промежуточные компоненты могут по своему усмотрению вызывать запрос GET так часто, как это необходимо для удовлетворения их собственных интересов. Пауки могут без разбора получать ресурсы для обновления своих индексов. Кэши можно предварительно извлечь. В ненадежной сети потерянные сообщения можно повторять так часто, как это необходимо для обеспечения хотя бы одного ответа.

Он будет использоваться для перезагрузки конфигураций, кеша и т. Д.

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

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

PUT, PATCH, DELETE... эти небезопасные методы с более конкретными семантики , чем POST; будут ли они подходящими, зависит от вашей модели ресурсов.

Важно помнить, что методы HTTP принадлежат домену документа (см. Доклад Джима Уэббера за 2011 год ). Описываемые вами эффекты, вероятно, не являются частью домена документа, а вместо этого вызывают побочные эффекты, вызываемые при изменении документов. , Это дает вам большую свободу в плане организации ваших документов для выполнения работы.

VoiceOfUnreason
источник