Як вибрати код статусу HTTP в API REST для "Ще не готово, спробуйте знову"? [зачинено]


152

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

Я не хочу повертати 404; це для речей, яких не існує. Це те, що існує, але його ще не створено. Ніби як відео YouTube, яке "обробляє". Я не думаю, що коди перенаправлення також не будуть правильними; немає іншої URL-адреси, яку слід спробувати.

Який правильний код статусу HTTP повернути у такому випадку?



7
По-перше, якщо thingy 1234 ще не має представництва GET, в якому сенсі він існує як ресурс (з точки зору клієнта)? Факт, що внутрішній сервер має чергу для створення 1234, не означає, що ресурс 1234 існує. По-друге, де клієнт отримав URI ... / thingyblob / 1234? Сервер, ймовірно, не повинен був надавати URI клієнтові, поки ресурс не отримав GET.
Енді Денні

1
Річ має інші властивості, які варто отримати, крім краплі. Час генерувати потребує лише крапля. Клієнт отримує їх, наприклад, сервер / thingyapi / thingy / 1234
JCCyC

10
Стандарт HTTP дає вказівки щодо того, які коди статусу використовувати в яких ситуаціях. Тому це питання насправді не ґрунтується насамперед на думці .
Raedwald

2
Як щодо 204"Без вмісту"? Показує, що сервер успішно обробив запит і не повертає жодного вмісту [наразі].
Тімо

Відповіді:


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. Прохання НЕ «був прийнятий для обробки» , то запит на практиці відкидаються
Адам

52

"Проблема", така, як вона, є на стороні сервера: клієнт зробив добре сформований запит, але сервер не може його задовольнити. Тому я схильний до "Помилки сервера", коду стану 5хх.

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
подолати те,

28

Я думаю, що 423 - Locked можна використовувати для цієї мети:

Код стану 423 (заблокований) означає джерело або ресурс призначення методу заблоковано. Ця відповідь ДОЛЖНА містити відповідну умову або код післяумови, наприклад, "замок-маркер-надісланий" або "безконфліктний-замок".


1
Відмінна відповідь! Цікаво, чому у неї немає більшої кількості відгуків.
lex82

10
Можливо тому, що це код HTTP WebDAV?
Стефан Л

1
З akka-http є StatusCode RetryWith = reg (c (449) ("Повторити с", "Запит слід повторити після виконання відповідної дії.")), Де дія буде зачекати і повторити
ozma

2
Багато в чому я згоден з цим. У мене схожа ситуація (у моєму випадку пошук за індексом, який ще не може бути заповнений). Семантично я вважаю, що це правильно. Однак, RFC для 423 заявляє, "Цей відповідь ДОЛЖЕН би містити відповідну умову або код післяумови, наприклад" надісланий замок-маркер "або" безконфліктний-замок "." Не знаєте, як це застосувати тут. І особисто я пішов би з 409 Conflict, але це було знято без коментарів - не знаю чому?
Адам

22

Я не хочу повертати 404; це для речей, яких не існує.

URL-адреса не відповідає запиту на корисні речі.

http://server/thingyapi/thingyblob/1234

Клієнт запитує речі, які не існують. Якби воно існувало, ви б їм їх віддали.

404.


1
Я радий, що хтось сказав це! Не можу повірити, що існує так багато людей, які думають 503, що це відповідна відповідь. Не кажучи вже про деякі інші дивні пропозиції.
Джейсон Дессосьє

Хоча я згоден, що 404 - це найбільш відповідна відповідь, це не відповідає на питання ОП, як вказати, коли річ буде доступна :-). Я думаю, що поле Retry-After видається найкращим кандидатом, але його можна офіційно використовувати лише для кодів 503 та 3xx. @Jason: Я думаю, що це пояснює деякі дивні пропозиції.
Ron Deijkers

Я думаю, що це найкраща відповідь. Ви можете повернути тіло у відповіді 404. Організм міг би вказати, що речі будуть доступні пізніше. Або також використовувати заголовок Retry-After. Тут потрібно трохи розтягнути стандарт, оскільки він не висвітлює цю справу добре.
ВВ.

4
Люди занадто пристосувались до сторінки 404 значення, не знайденої, що вони не можуть логічно розмежувати це в контексті API.
Людина-булочка

1
Це sooooo 404. Thingyblob ще не існує, ні коли-небудь .. Для http його нерелевантно, якщо він коли-небудь буде доступний. На даний момент його не існує, і його 404. Коли він буде доступний, є ще одна проблема, яку можна вирішити, натиснувши повідомлення з сервера на клієнт, сказавши, що існує: 1234. Виконайте знову і вуаля ..
100р

21

Інший варіант: 503 - Service Unavailable.


5
За словами W3C, це не те, що ви хочете сказати клієнтові (хоча це означає "прийти знову" якимось чином): "Сервер наразі не в змозі обробити запит через тимчасову перевантаження або обслуговування сервера. це тимчасова умова, яка буде полегшена після деякої затримки. Якщо відомо, тривалість затримки МОЖЕ бути вказана у заголовку "Повторне завантаження". Якщо не вказано "Повторне завантаження", клієнт ДОЛЖЕН би обробляти відповідь так, як це було б для 500 відповідей ".
skalee

4
Сервіс недоступний, сервіс доступний, але обробка не завершена. Отже, 503 - це, мабуть, не дуже гарна ідея.
Іштяке Хан

17

Оскільки ваш ресурс не готовий, ви, ймовірно, знаєте, коли (приблизно) він буде доступний і коли клієнт може повторно спробувати його запит. Це означає, що ви можете використовувати заголовок Retry-After . Цей заголовок дійсний з 503 (Служба недоступна), що означає, що весь сайт не працює для обслуговування та 3xx (Перенаправлення) відповідей.

На мою думку, 302 (Знайдено) із заголовком Retry-After було б найкращим варіантом, але я не впевнений, чи може поле поля відповіді заголовка відповідати URL-адресу запиту. Це все одно кругова переадресація.


3
Навіть якщо це дозволено, якщо клієнт не реалізував підтримку заголовка Retry-After, перенаправлення 3xx на ту ж сторінку може врешті закінчитися 503 ... (необов'язково із заголовком Retry-After, звичайно)
Ron Deijkers

1
Retry-After також діє з HTTP 429 "Занадто багато запитів", доданим RFC 6585 (квітень 2012). Це може бути доречно, якщо причиною того, що ресурс ще не готовий, є те, що клієнт надає серверу занадто багато роботи.
Сілас С. Браун

8

409 Конфлікт

Вказує на те, що запит не може бути оброблений через конфлікт у запиті, наприклад конфлікт редагування у випадку кількох оновлень. [Джерело Вікіпедії.]

Це може бути доречно.

Якщо ви не можете виконати запит, повернувши дані - це не буде успіхом. Я думаю, що 202 припускає, що сервер поставив його в чергу, і він виконає запит пізніше. Але у вашому випадку запит зараз є даними та не вдався. Якщо ви повторите спробу пізніше, це інший запит.

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


2
Не впевнений, чому це було проголошено. Схоже, правильна відповідь для мене. З RFC: "Код статусу 409 (конфлікт) вказує на те, що запит не вдалося виконати через конфлікт із поточним станом цільового ресурсу. Цей код використовується в ситуаціях, коли користувач міг би вирішити конфлікт і повторно подайте запит. "Ви попросили ресурс, який сервер не може повернути, оскільки сервер знаходиться в процесі оновлення цього ресурсу, тобто через поточний стан ресурсу. Клієнт може вирішити це, чекаючи та повторно надсилаючи
Адам

1
@Adam Я думаю, що під впливом "користувач міг би вирішити конфлікт", це те, що щось про повторне подання було б інакше, крім простого очікування.
Цілісний розробник

3

501 - Не реалізовано

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

Ось посилання на резюме помилок 5xx .


4
Для цього питання здається, що сама функція існує, але запитуваний елемент цього не робить.
Люк

Опис @Luke 501 за посиланням у моїй відповіді, "... у нього немає можливості виконати запит. Зазвичай це передбачає наявність у майбутньому ". Це відповідає саме тому, про що просила ОП. Незалежно від того, є чи ні дані на його серверах чи БД. Кінцевим результатом є те, що наразі він не доступний через API. Тому API не може виконати запит, але хоче зазначити, що він буде доступний у майбутньому через http-код.
Dan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.