Использовать http статус 202 для асинхронных операций - PullRequest
52 голосов
/ 22 февраля 2011

Я пишу REST API для службы, которая будет принимать введенные пользователем данные. Я хотел бы сохранить все операции полностью асинхронными, в том числе PUT, POST, DELETE и, возможно, даже запросы GET. Моя идея состоит в том, чтобы получить запрос, обработать его достаточно, чтобы убедиться, что это действительный запрос, а затем передать принятый ответ HTTP 202 вместе с URL-адресом, где данные в конечном итоге будут доступны, и токеном, чтобы последующие запросы могли быть сопоставлены с обработанными данными. , Если запрос недействителен, я отправлю HTTP 400.

Клиент будет нести ответственность за проверку URL-адреса, который я предоставил им в будущем, и передачу токена. Если данные доступны, я возвращаю обычные 200 или 201, но если я все еще обрабатываю запрос, я отправлю еще 202, указывающие, что обработка не завершена. В случае ошибок при обработке данных я отправлю статус 4xx или 5xx при необходимости.

Причина, по которой я хочу это сделать, заключается в том, чтобы я мог выгрузить все действительные запросы в пул запросов и заставить рабочих извлекать их из очереди и обрабатывать запросы по мере их доступности. Поскольку я не знаю размера пула или количества доступных рабочих, я не могу быть уверен, что смогу получать запросы достаточно быстро, чтобы удовлетворить 30-секундный лимит Google App Engine.

У меня вопрос: извращаю ли я REST, обрабатывая запросы таким образом? Например, браузеры, похоже, требуют немедленных ответов на запросы. Для моих HTML-страниц я планирую ответить структурированной страницей, а затем использовать AJAX для обработки запросов данных.

Меня больше всего интересуют любые мнения или опыт обработки данных с использованием REST таким образом.

Ответы [ 4 ]

36 голосов
/ 22 февраля 2011

Я думаю, что ваше решение в порядке, Http status 202 - это правильный ответ для использования в данном конкретном случае, указывая, что запрос принят для обработки, но обработка не былазавершено .

Что бы я немного изменил в вашем рабочем процессе, это Http status последующих запросов.

Как вы сказали, 202 response должен вернуть Location header, указавURL-адрес, который клиент должен использовать для отслеживания состояния своего предыдущего запроса.
Вызов этого Проверить статус-моего-процесса , вместо возврата 202 в случае ожидания процесса,Я бы вернул:

  1. 200 OK, когда запрошенный процесс еще не завершен.Ответ должен содержать описание ожидающего статуса процесса.
  2. 201 Created после завершения обработки.Ответ в случае GET / PUT / POST должен содержать Location для запрошенного / созданного / обновленного ресурса.
25 голосов
/ 02 марта 2012

Добавление двух моих центов к старому вопросу.Моя идея похожа на предложения systempuntoout и Avi Flax.

Я согласен, что ответ HTTP 202 подходит для первоначального запроса с перенаправлением на другой ресурс через заголовок Location.

Я думаю, что URL Location, вероятно, должен включать токен, на который вы ссылаетесь, чтобы соответствовать общим ожиданиям перенаправления Location.Например, Location: /queue?token={unique_token} или Location: /task/{unique_token}.

Я также думаю, что ресурс, используемый для проверки состояния процесса, должен возвращать ответ HTTP 200, когда действие «проверка состояния» выполнено успешно (неHTTP 202, поскольку это подразумевает, что текущий запрос был "принят").

Тем не менее, я думаю, что при создании новой сущности "проверка статуса" должна вернуть HTTP 303 ( См. Прочее ) ответ с заголовком Location для новой сущности после ее создания.Это более целесообразно, чем отправка HTTP 201, поскольку ничего не было создано из-за запроса GET, только что выполненного для проверки состояния.

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

6 голосов
/ 13 ноября 2013

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

С точки зрения клиента

Начнем с начального HTTP-запроса.Прежде всего, запрос должен быть POST.Вы отправляете сообщение на сервер для создания ресурса.GET и PUT недопустимы в этом случае, потому что:

  • GET недопустим в этом контексте, потому что GET предназначен для получения ресурса в определенном месте
  • PUT являетсянедопустимо, потому что вы не создаете запрос, вы просите сервер создать запрос.

С точки зрения сервиса

Итак, вы отправляетеPOST к серверу для обработки запроса.На самом деле сервер имеет 3 возможных возвращаемых значения (не считая ошибок 4xx и 5xx):

  • «201 Created» означает, что служба получила запрос и смогла обработать его немедленно или в пределах приемлемоговременной период.Этот период времени полностью соответствует дизайну сервиса.Это зависит от разработчика сервиса, чтобы определить это.
  • «202 принято» означает, что служба получила запрос и обрабатывает его.Это используется, когда служба знает, что что-то займет некоторое времяДругая перспектива заключается в том, что если служба зависит от какой-либо другой асинхронной операции, которая не может определить результат, она должна вернуть ответ «202 Принят».Наконец, некоторые разработчики сервисов могут просто всегда возвращать «202 принято» независимо от того, как быстро это может быть сделано.
  • В некоторых случаях вы получите «302 найдено».Это обычно происходит, когда служба может идентифицировать запрос как генерирующий ресурс, который уже существует (и все еще действителен и не находится в состоянии ошибки), и что повторное использование существующего ресурса является приемлемым.Не все службы работают так: публикация комментария в ветке всегда должна создавать новые ресурсы.Другие службы делают: опубликовать набор критериев, чтобы получить список врачей, производит тот же список врачей.Если эту информацию можно использовать повторно, используйте ее повторно.
  • Со всеми этими ответами HTTP-заголовок «Location» возвращается клиенту, содержащему, где находится ресурс.Это важно, и когда некоторые люди склонны расходиться, как вы увидите позже.Если ресурс может быть повторно использован с другими запросами, «Местоположение» должно действительно генерироваться таким образом, чтобы одни и те же запросы всегда генерировали одинаковые URL-адреса.Это обеспечивает хорошее кэширование и повторное использование.

Когда служба успешно завершила запрос, она создаст ресурс в местоположении, которое было возвращено клиенту.

Теперь я начинаю видеть вещи, немного отличающиеся от приведенного выше ответа.

Если службе не удается выполнить запрос, она все равно должна создать ресурс в месте, которое было возвращено клиенту.Этот ресурс должен указывать причину сбоя.Гораздо гибче иметь ресурс, предоставляющий информацию об ошибках, чем пытаться вставить его в протокол HTTP.

Если служба получает запрос на этот ресурс до его завершения, она должна вернуть «404 НеНайденный".Причина, по которой я считаю, что это должно быть «404 Not Found», заключается в том, что он действительно не существует.Спецификации HTTP не говорят, что «404 Not Found» может использоваться только для случая, когда ресурс никогда не будет существовать, просто потому, что его там сейчас не существует.Этот тип ответа на асинхронный поток опроса, на мой взгляд, совершенно корректен.

Существует также сценарий, когда ресурс должен быть там только в течение фиксированного времени.Например, это могут быть данные, основанные на источнике, который обновляется каждую ночь.В этих случаях должно произойти то, что ресурс должен быть удален, но службе следует предоставить индикатор, который он может знать, чтобы вернуть код состояния «410 Gone».Это в основном говорит клиенту, что ресурс был здесь, но больше не доступен (то есть: возможно, истек).Типичным действием клиента будет повторная отправка запроса.

С точки зрения клиента снова

Когда клиент получает ответ для своего первоначального POST, он получает«Местоположение» и делает запрос к службе, используя этот URL, используя GET (опять же, не POST).Служба обычно отвечает следующими значениями:

  • «200 OK» означает, что запрос выполнен.Результат запроса возвращается в теле содержимого, предоставляя содержимое в формате, определенном заголовком HTTP Accept.
  • «404 Not Found» сообщит клиенту, что запрос еще не завершен, ресурсеще не существует, и в этом случае следует повторить попытку позже.
  • «410 Gone» будет возвращено в случаях, когда клиент может попытаться получить ресурс через длительный период времени, и этотам больше нетВ этом случае он должен просто повторно отправить исходный запрос

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

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

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

2 голосов
/ 26 ноября 2016

FWIW, Microsoft Flow использует такой шаблон.
При первом вызове возвращается 202 с заголовком местоположения.Последующие вызовы возвращают либо: 1. Если все еще обрабатывается -> 202 с заголовком местоположения.Заголовок loc может быть другим, что обеспечивает способ передачи состояния между вызовами (и, возможно, делает сервер без сохранения состояния!).2. Если сделано -> 200.

Подробности по адресу: https://github.com/jeffhollan/LogicAppsAsyncResponseSample

...