Использовать HTTP-статус 202 для асинхронных операций

Я пишу 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 таким образом.

Ответ 1

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

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

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

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

Ответ 2

Добавление моих двух центов к старому вопросу. Моя идея подобна предложениям 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 для проверки состояния.

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

Ответ 3

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 4

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

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