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

152

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

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

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

JCCyC
источник
3
Несколько связано
Роб Хруска
7
Во-первых, если штука 1234 еще не имеет GET-способного представления, в каком смысле она существует как ресурс (с точки зрения клиента)? Тот факт, что внутри сервера существует задание в очереди для создания 1234, не означает, что ресурс 1234 существует. Во-вторых, где клиент получил URI ... / thingyblob / 1234? Сервер, вероятно, не должен был предоставлять этот URI клиенту до тех пор, пока ресурс не станет фактически GET-совместимым.
Энди Денни
1
У вещи есть другие свойства, которые стоит приобрести, кроме капли. Это только блоб, который требует времени для генерации. Клиент получает их, например, через сервер / thingyapi / thingy / 1234
JCCyC
10
Стандарт HTTP предоставляет руководство о том, какие коды состояния использовать для каких ситуаций. Таким образом, этот вопрос не является главным образом основанным на мнении .
Raedwald
2
Как насчет 204"Нет контента"? Is указывает, что сервер успешно обработал запрос и не возвращает никакого содержимого [в настоящее время].
Тимо

Ответы:

77

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

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

matsev
источник
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, «Внутренняя ошибка сервера» , что было бы неправильно.

Raedwald
источник
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.

funroll
источник
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 запроса. В любом случае, это круговое перенаправление.

skalee
источник
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.
Дан