Как выбрать код состояния HTTP в REST API для «Пока не готов, повторите попытку позже»? [закрыто]


152

Я разрабатываю RESTful API, в котором http://server/thingyapi/thingyblob/1234для загрузки возвращает файл (он же «blob»), связанный с thingy # 1234. Но может случиться так, что запрос сделан в то время, когда файл не существует на сервере, но наиболее определенно будет доступен позже. На сервере есть пакетный процесс, который генерирует все BLOB-объекты для всех штук. Thingy 1234 уже существует, и его данные, кроме блоба, уже доступны. Серверу еще не удалось сгенерировать BLOB-объект штуковины 1234 года.

Я не хочу возвращать 404; это для штуковин, которых не существует. Это вещь, которая существует, но ее блоб еще не сгенерирован. Вроде как видео на YouTube это "обработка". Я не думаю, что коды перенаправления были бы правильными; нет «другого» URL, чтобы попробовать.

Какой правильный код статуса HTTP нужно вернуть в таком случае?



7
Во-первых, если штука 1234 еще не имеет GET-способного представления, в каком смысле она существует как ресурс (с точки зрения клиента)? Тот факт, что внутри сервера существует задание в очереди для создания 1234, не означает, что ресурс 1234 существует. Во-вторых, где клиент получил URI ... / thingyblob / 1234? Сервер, вероятно, не должен был предоставлять этот URI клиенту до тех пор, пока ресурс не станет фактически GET-совместимым.
— Энди Денни

1
У вещи есть другие свойства, которые стоит приобрести, кроме капли. Это только блоб, который требует времени для генерации. Клиент получает их, например, через сервер / thingyapi / thingy / 1234
— JCCyC

10
Стандарт HTTP предоставляет руководство о том, какие коды состояния использовать для каких ситуаций. Таким образом, этот вопрос не является главным образом основанным на мнении .
— Raedwald

2
Как насчет 204"Нет контента"? Is указывает, что сервер успешно обработал запрос и не возвращает никакого содержимого [в настоящее время].
— Тимо

Ответы:


77

Я предлагаю 202 - Accepted. Из документации :

Запрос принят к обработке, но обработка не завершена. [...] Его цель - позволить серверу принять запрос для какого-либо другого процесса (возможно, пакетно-ориентированного процесса, который выполняется только один раз в день)


62
-1: Это имеет смысл для запроса, который инициирует процесс, который в конечном итоге создает "thingy # 1234", но не для запроса GET, выданного впоследствии для самого "thingy # 1234". В частности, 202 предполагает, что в результате запроса GET служба отправит данные для «штуки # 1234» в более поздний момент времени. Это просто не правильно.
— Сэм Харвелл,

7
В нем также говорится: «Сущность, возвращаемая с этим ответом, ДОЛЖНА включать в себя указание текущего состояния запроса и либо указатель на монитор состояния, либо некоторую оценку того, когда пользователь может ожидать выполнения запроса», так что это будет хороший способ сообщить клиенту, что блоб еще не готов, и способ узнать, когда он готов.
— Реми Лебо

3
Я бы сказал, что «принято к обработке» означает, что вы сохраняете запрос, который будет обработан позже. Если это просто игнорируется, вы должны вернуть код 4xx или 5xx, чтобы указать клиенту, что он может попробовать еще раз.
— Люк

3
102 (обработка) иногда кажется разумным выбором, даже если он указан в спецификации webdav.
— Акостадинов

2
Не могу не согласиться с этим ответом. Сервер ничего не возвращает или не планирует (не выполняет никакой обработки из-за этого запроса - что он в любом случае не должен делать для GET). Таким образом, ресурс каким-то образом недоступен для клиента. Это следует рассматривать как ошибку, поэтому код 2XX не подходит. Что-то в пространстве 4XX или 5XX. Запрос не «принят к обработке» , на практике этот запрос отклоняется
— Адам

53

«Проблема», как она есть, на стороне сервера: клиент сделал правильно сформированный запрос, но сервер не может удовлетворить его. Так что я склонен к «Ошибка сервера», код состояния 5xx.

Quoth RFC 7231 (текущий стандарт HTTP, акцент добавлен):

Класс кода состояния 5xx (Ошибка сервера) указывает, что сервер знает, что он допустил ошибку или не может выполнить запрошенный метод . За исключением случаев ответа на запрос HEAD, сервер ДОЛЖЕН послать представление, содержащее объяснение ситуации с ошибкой, и является ли это временным или постоянным условием.

Заметка

  • «ошибся или неспособен выполнить запрос»: несмотря на название «Ошибка сервера», они относятся не только к ошибкам сервера.
  • « временный или постоянный»: эти коды подходят для временно недоступных ресурсов, таких как ваш.

Из доступных кодов, я бы сказал, 503, «Служба недоступна» как нельзя лучше подходит:

Код состояния 503 (служба недоступна) указывает, что сервер в настоящее время не может обработать запрос из-за временной перегрузки или планового обслуживания, которое, вероятно, будет облегчено после некоторой задержки. Сервер МОЖЕТ отправить поле заголовка Retry-After ..., чтобы предложить клиенту соответствующее время ожидания, прежде чем повторять запрос.

Примечание:

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

Определение собственного кода статуса 5xx (например, 591), хотя и разрешено , будет иметь неверную семантику:

клиент ДОЛЖЕН понимать класс любого кода состояния, как указано первой цифрой, и обрабатывать нераспознанный код состояния как эквивалентный коду статуса x00 этого класса

Клиенты будут рассматривать ваш собственный код состояния как 500, «Внутренняя ошибка сервера» , что было бы неправильно.


2
Я не вижу, как это лучше, чем 202: benramsey.com/blog/2008/04/…
— JCCyC

4
@JCCyC ваш блог дает хороший аргумент для возврата 202 в ответ на запрос на создание чего-либо (POST или PUT). Вопрос, кажется, задает вопрос о том, что вернуть для GET.
— Raedwald

@JCCyC это можно рассматривать как другой оттенок неготовности: представьте себе аджакс для этого ресурса, предпочитаете ли вы 202 как статус успеха или 503 как статус ошибки? так что вы можете видеть, какое значение вы предпочитаете неявным образом в контексте реакции вашего приложения на ответ
— rloth

также мне нравится практический аспект «Retry-After», который хорошо сочетается с чем-то, что «не готово»
— rloth

1
NB: «Retry-After» также может быть 307 - TEMPORARY REDIRECTполезен, если вы хотите заставить клиентскую сторону ждать в другом месте, пока ваш ресурс «готовится»
— rloth

28

Я думаю, что 423 - Locked можно использовать для этой цели:

Код состояния 423 (заблокирован) означает, что источник или целевой ресурс метода заблокирован. Этот ответ ДОЛЖЕН содержать соответствующий код предусловия или постусловия, такой как «lock-token-submit» или «no-конфликтаing-lock».


1
Отличный ответ! Интересно, почему у него нет больше голосов.
— lex82

10
Возможно, потому что это HTTP-код WebDAV?
— Стефан Л

1
Из akka-http есть StatusCode RetryWith = reg (c (449) («Повторить с», «Запрос следует повторить после выполнения соответствующего действия.»)), Где действие будет ждать и повторять
— ozma

2
Во многом я согласен с этим. У меня похожая ситуация (в моем случае поиск по индексу, который еще не заполнен). Семантически, я думаю, что это правильно. Однако в RFC для 423 говорится: «Этот ответ ДОЛЖЕН содержать соответствующий код предусловия или постусловия, такой как« lock-token-submit »или« no-конфликтаing-lock »». Не уверен, как применить это здесь. И лично я пошел бы с 409 Конфликтом, но это было понижено без комментариев - не уверен почему?
— Адам

22

Я не хочу возвращать 404; это для штуковин, которых не существует.

URL не соответствует запросу на штуку.

http://server/thingyapi/thingyblob/1234

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

404.


1
Я рад, что кто-то сказал это! Я не могу поверить, что есть так много людей, которые считают 503это правильным ответом. Не говоря уже о некоторых других странных предложениях.
— Джейсон Десросье

Хотя я согласен, что 404 является наиболее подходящим ответом здесь, он не отвечает на вопрос ОП, как указать, когда вещь доступна :-). Я думаю, что поле Retry-After кажется лучшим кандидатом, но оно может официально использоваться только для кодов 503 и 3xx. @Jason: я думаю, это объясняет некоторые странные предложения.
— Рон Дейкерс

Я думаю, что это лучший ответ. Вам разрешено вернуть тело в ответе 404. Тело может указывать, что вещь будет доступна позже. Или используйте заголовок Retry-After. Стандарт нужно немного растянуть здесь, потому что он не очень хорошо подходит для этого случая.
— WW.

4
Люди слишком привыкли к тому, что страница 404 не обнаружила, что они не могут логически отделить это в контексте API.
— Человек

1
Это оооочень 404. Thingyblob еще не существует или никогда. Для http его не имеет значения, будет ли он когда-либо доступен. На данный момент его не существует, и его 404. Когда он будет доступен, есть еще одна проблема, которая может быть решена путем передачи сообщения от сервера к клиенту: sayin thingyblob: 1234 доступно.
— 100

21

Другой вариант: 503 - Service Unavailable.


5
Согласно W3C, это не то, что вы хотите сказать клиенту (хотя это означает, что «приходите снова» каким-то образом): «Сервер в настоящее время не может обработать запрос из-за временной перегрузки или обслуживания сервера. Это означает, что это временное условие, которое будет смягчено после некоторой задержки. Если известно, длина задержки МОЖЕТ быть указана в заголовке Retry-After. Если Retry-After не задано, клиент ДОЛЖЕН обработать ответ, как это было бы для 500 ответ. "
— Скали

4
Сервис не доступен, сервис доступен, но обработка не завершена. Так что 503, вероятно, не очень хорошая идея.
— Иштьяк Хан

17

Поскольку ваш ресурс не готов, вы, вероятно, знаете, когда (приблизительно) он будет доступен и когда клиент может повторить свой запрос. Это означает, что вы можете использовать заголовок Retry-After . Этот заголовок действителен с 503 (служба недоступна), что означает, что весь сайт не работает для обслуживания, и с ответами 3xx (перенаправление).

По моему мнению, 302 (найдено) с заголовком Retry-After будет лучшим вариантом, но я не уверен, может ли поле Location заголовка ответа быть равно URL запроса. В любом случае, это круговое перенаправление.


3
Даже если это разрешено, если клиент не реализовал поддержку заголовка Retry-After, перенаправление 3xx на ту же страницу может в конечном итоге закончиться 503 ... (опционально, конечно, с заголовком Retry-After)
— Рон Дейкерс

1
Retry-After также действителен для HTTP 429 «Too Many Requests», добавленного RFC 6585 (апрель 2012 г.). Это может быть уместно, если причина того, что ресурс еще не готов, заключается в том, что клиент слишком много работал с сервером.
— Сайлас С. Браун

8

409 Конфликт

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

Это может быть уместно.

Если вы не можете выполнить запрос, вернув данные - это не удача. Я думаю, что 202 предполагает, что сервер поставил в очередь запрос, и он выполнит запрос позже. Но в вашем случае запрос для данных сейчас и не удалось. Если вы повторите попытку позже, это другой запрос.

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


2
Не уверен, почему за это проголосовали. Похоже, правильный ответ для меня. Из RFC: «Код состояния 409 (Конфликт) указывает, что запрос не может быть выполнен из-за конфликта с текущим состоянием целевого ресурса. Этот код используется в ситуациях, когда пользователь может разрешить конфликт и повторно отправить запрос. "Вы запросили ресурс, который сервер не может вернуть, потому что сервер находится в процессе обновления этого ресурса, то есть из-за текущего состояния ресурса. Клиент может решить эту проблему путем ожидания и повторной отправки
— Адам

1
@ Adam Я думаю, что смысл в «пользователь может решить конфликт» состоит в том, что что-то в повторной передаче будет отличаться, кроме простого ожидания.
— Целостный разработчик

3

501 - не реализовано

Точно так же, как это звучит. Функция, которая еще не реализована, но подразумевает доступность в будущем.

Вот ссылка на резюме ошибок 5xx .


4
По этому вопросу звучит так, как будто сама функция существует, а запрашиваемый элемент - нет.
— Люк

Описание Луки 501 по ссылке в моем ответе: «... ему не хватает возможности выполнить запрос. Обычно это подразумевает доступность в будущем ». Это выполняет именно то, о чем просил ОП. Независимо от того, есть ли данные на его серверах или в БД. Конечным результатом является то, что он пока недоступен через API. Поэтому API не может выполнить запрос, но хотел бы подразумевать, что он будет доступен в будущем через код http.
— Дан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.