Неправильно ли возвращать 202 «Принято» в ответ на HTTP GET?


89

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

Первый запрос GET, полученный для ресурса, запускает вычисление на сервере. Если вычисление завершается в течение нескольких секунд, возвращается вычисленное представление. В противном случае возвращается код состояния 202 «Принято», и клиент должен опрашивать ресурс, пока не станет доступно окончательное представление.

Причина такого поведения следующая: если результат доступен в течение нескольких секунд, его необходимо получить как можно скорее; в противном случае не важно, когда он станет доступен.

Из-за ограниченной памяти и огромного количества запросов ни NIO, ни длинный опрос не являются вариантом ( т.е. я не могу поддерживать почти достаточное количество открытых подключений, и даже не могу вместить все запросы в память; один раз «несколько секунд») прошли, настаиваю на лишние запросы). Точно так же ограничения клиентов таковы, что они не могут вместо этого обрабатывать обратный вызов завершения. Наконец, обратите внимание, что я не заинтересован в создании "фабричного" ресурса, на который отправляется один POST, поскольку дополнительные циклы передачи означают, что мы нарушаем кусочное ограничение в реальном времени больше, чем требуется (кроме того, это дополнительная сложность; кроме того, это ресурс, который выгода от кеширования).

Я предполагаю, что есть некоторые разногласия по поводу возврата кода состояния 202 «Принято» в ответ на запрос GET, поскольку я никогда не видел этого на практике, и его наиболее интуитивно понятное использование - это ответ на небезопасные методы, но я никогда не нашел что-нибудь, что конкретно его обескураживало. Более того, разве я не сохраняю и безопасность, и идемпотентность?

Итак, что люди думают об этом подходе?

EDIT : я должен упомянуть, что это для так называемого бизнес-веб-API, а не для браузеров.


2
Я лично считаю, что это хороший вариант, это точное определение 202. То, что он редко используется на практике, - ИМХО больше, потому что немногие веб-разработчики заботятся о правильных кодах состояния, поскольку они больше привыкли к взаимодействию браузера / пользовательского агента, и в этом случае a не 202дает им видимой подсказки (дайте им, 200и они счастливы. ..).
Wrikken 04

1
@ user359996, просто используйте 200. 202это то, что должно быть, но на практике люди этого не ожидают 202.
Pacerier

однако для практического использования требуется ETA для 200.
Роб

Ответы:


66

Если это для четко определенного и документированного API, 202звучит как раз для того, что происходит.

Если это для общедоступного Интернета, я бы слишком беспокоился о совместимости клиентов. Я видел так много if (status == 200)жестко запрограммированных .... В этом случае я бы вернул 200.

Кроме того, RFC не указывает, что использование 202 для запроса GET является неправильным, но делает четкие различия в других описаниях кода (например, 200).

Запрос принят в обработку, но обработка не завершена.


16

Мы сделали это для недавнего приложения, клиент (пользовательское приложение, а не браузер) отправил запрос POST, и сервер вернул бы 202 с URI для отправляемого «задания» - клиент будет использовать этот URI для опроса для результат - похоже, это хорошо сочетается с тем, что было сделано.

В любом случае самое важное - это документировать, как работает ваш сервис / API, и что означает ответ 202.


+1 Спасибо за комментарий. Хороший момент по поводу документации. Но обратите внимание на уточняющие правки в моем вопросе (ищите "фабрику").
user359996 04

Что ж, вы можете опустить этот URI в ответе, если вы просто хотите опросить тот же URI, который вы изначально запрашивали. (Просто задокументируйте, как это должно работать :-))

Хорошая идея, но помните, что мне нужно кеширование, поэтому без POST. Более того, URI указывает ресурс, а не метод. Я использую подход RESTful, а не RPC (извините, еще одно неуказанное ограничение - мое плохое).
user359996 04

Чтобы быть точным, под «RESTful» я на самом деле подразумеваю «ресурсоориентированный», что технически немного больше, чем указано в ограничениях REST.
user359996 04

12

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

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

Все это очень пуритански и плохо практикуется в дикой природе, поэтому вы, вероятно, в безопасности, вернув 202. GET должен вернуть 200. POST может вернуть 200, если он завершен, или 202, если он не выполнен.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html


4
Очень хорошее мышление, но я не уверен, применимо ли оно здесь: из того, что говорит OP, это кажется правильным запросом GET (в том смысле, что он ничего не меняет на сервере), просто требуется больше времени для вычисления и в этот случай необходимо получить в другое время. Может быть, ОП может дать авторитетный комментарий. Это для API, так что хорошо быть «пуританином» ради чистого интерфейса
Пекка

О, туше пекка. Вы правы, GET - лучший способ. И я не думаю, что HTTP spc действительно учитывал GET, которые не готовы. Так что он мог пойти любым путем
Длонгнекер

7
(Теперь не имеет значения) авторитетный комментарий: Да, я считаю это идемпотентным. Ресурс не является ни модифицируется , ни создан, а это представление еще не было вычислено.
user359996 04

1
Где это сказано? Кроме того, если я верну 200, клиент должен ожидать, что представление было возвращено, но это не так.
user359996 04

1
Беру обратно. 202, похоже, не соответствует только GET или POST. Именно тот образ мышления, в котором я находился, когда смотрел на протокол, заставил меня подумать, что 202 существует только для запросов GET. 202 подойдет для ваших целей.
Dlongnecker

0

В случае ресурса, который должен иметь представление объекта, который четко указан идентификатором (в отличие от ресурса «фабрики», как описано в вопросе), я рекомендую использовать метод GET и в ситуация, когда объект / представление недоступен из-за ленивого создания или любой другой временной ситуации, используйте код ответа 503 Service Unavailable, который более подходит и был фактически разработан для ситуаций, подобных этой.

Причины этого можно найти в RFC для самого HTTP (пожалуйста, проверьте описание кода ответа 503), а также на многих других ресурсах.

Сравните с кодом статуса HTTP для временно недоступных страниц . Хотя этот вопрос касается другого варианта использования, на самом деле он относится к той же функции HTTP.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.