Код состояния HTTP для частичного успешного запроса

116

У меня есть приложение, которое отправляет сообщения пользователям. В почтовом запросе передается строка XML, содержащая всех пользователей, которые должны получить это конкретное сообщение. Если какой-либо из пользователей в списке не существует, я возвращаю список отсутствующих пользователей клиенту для дальнейшей оценки.

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

Этой проблемы можно было бы избежать, если бы не было разрешено включать в список отсутствующих пользователей. Тогда при отправке будет просто ошибка 4xx. Но формировать API таким образом нет смысла. С другой стороны, я мог бы рассматривать состояние ошибки как чисто конкретное приложение. Но посылать 200 кажется неправильным. И было бы неплохо дать клиенту подсказку, когда нужно внимательно изучить ответ об ошибке. например, чтобы не отправлять сообщения этим пользователям снова и снова

Норберт Хартл
источник

Ответы:

66

Я имел дело с очень похожей проблемой. В этом случае я вернул

207 Мульти-статус

Это не строгий HTTP, это часть расширения WebDAV, поэтому, если у вас нет контроля над клиентом, это вам не подходит. Если да, то можно сделать что-то вроде этого:

   <?xml version="1.0" encoding="utf-8" ?>
   <D:multistatus xmlns:D='DAV:'>
     <D:response>
       <D:user>user-123</D:user>
       <D:status>success</D:status>
     </D:response>
     <D:response>
       <D:user>user-789</D:user>
       <D:status>failure</D:status>
     </D:response>
   </D:multistatus>

Но опять же, это расширение HTTP, и вам также необходимо контролировать клиента.

Кайлар
источник
3
Я думал об использовании этого, но мне это было не совсем удобно. Спасибо!
Норберт Хартл
Приятно то, что вы можете возвращать столько или меньше подходящих данных, сколько захотите, что особенно полезно для наборов смешанных данных, например, где некоторые не работают, а некоторые проходят.
Kylar
Я понимаю. Я просто пытаюсь избежать дополнительного уровня обработки статуса (что не очень приятно, ИМХО). Большая часть моего кода работает с HTTP. И я думаю, что описанный мной вариант использования обойдется без.
Норберт Хартл,
Вы всегда можете отправить тело обратно - отправьте 200 с ответом JSON или как хотите, чтобы определить, какие из них были успешными.
Kylar
Да, я знаю. Но если вы вернете тело, вам нужно его разобрать. И в этот момент вы вводите второй уровень обработки логики приложения. Это увеличивает сложность, и тогда вам нужна веская причина для этого.
Норберт Хартл,
66

У меня была такая же проблема, и в итоге я использовал два разных решения:

  • Код возврата HTTP 202: Accepted, указывающий, что запрос был в порядке, но нет гарантии, что все действительно прошло должным образом.
  • Верните нормальный 200ответ в ответ, но включите список того, что не соответствует действительности в теле ответа.

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

Арне
источник
5
Разве 202 не относится к чему-то вроде очереди?
Sinaesthetic
6
Да, @Sinaesthetic. Согласно последней спецификации HTTP 1.1, «(...) запрос был принят для обработки, но обработка не была завершена». Так что для частичного успеха 202 не подходит.
Huercio 09
-4

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

Юсуф
источник
В MDN указано следующее: «Код ответа HTTP 206 с частичным статусом успешного завершения содержимого указывает, что запрос выполнен успешно и имеет тело, содержащее запрошенные диапазоны данных, как описано в заголовке запроса диапазона». Насколько я понимаю, 206 Partial Content предназначен исключительно для запросов с диапазоном контента.
sbbs 01
-14

Протокол передачи гипертекста имеет дело со стороной передачи. В нем нет кодов ошибок для устранения ошибок на уровне приложения.

Вернуть 200 - это правильное решение. Что касается HTTP, запрос был получен правильно, обработан должным образом, и вы отправляете ответ обратно. Итак, на уровне HTTP все в порядке. Любые ошибки или предупреждения, связанные с приложением, работающим поверх http, должны быть внутри ответа. Это также предотвратит некоторые неприятные проблемы, с которыми вы можете столкнуться с прокси-серверами, которые могут не обрабатывать определенные ответы так, как вы ожидаете.

AVEE
источник
18
HTTP - это протокол уровня приложения. Вы не можете просто поставить это на уровень транспорта и приложения. Если вы думаете об OSI, то HTTP находится на уровнях 5-7. HTTP несколько отличается. Большинство заголовков и кодов возврата действительно зависят от приложения. Коды зависят только от информации, указанной в сущностях протокола HTTP, а не от элементов пользовательского формата приложения. Что касается 200, я бы сказал, что ваше определение совершенно неверно, если оно применяется к глаголам, не являющимся POST. Но POST немного меняет игру, и в этом контексте ваше предположение «правильно обработано» также не является уверенным
Норберт Хартл
Строго говоря, OSI рассматривает HTTP как протокол уровня приложения, и при разговоре с «обычным» веб-сервером это верно. Но в вашем случае вы используете свой собственный протокол поверх HTTP, как это делают многие приложения в наши дни. В этом типе использования HTTP просто предоставляет транспорт. (Ваше приложение отправляет сообщения пользователям, а не передает гипертекст ...)
AVee
2
Просто быть чистым. HTTP в стиле REST ориентирован на ресурсы. В этом контексте 200 означает идентификатор (указанный вами ресурс) вместо 3xx, который указывает в направлении идентичности. Использование POST превращает URI ресурса в URI обработки, и коды ошибок должны с этим справиться. Контекст немного меняется, и определение вещей становится немного расплывчатым или, по крайней мере, трудным для понимания
Норберт Хартл
1
Сдвиг контекста также означает отсутствие подходящих кодов ошибок, поскольку протокол никогда не разрабатывался с учетом этого контекста ;-) Я также думаю, что вы должны быть осторожны с использованием кодов ошибок, поскольку прокси-серверы, как правило, работают с ними, заменяя ваш ответ на пользовательская страница ошибки, это может быть настоящий PITA.
AVee
1
В любом случае, спасибо, что ответили на мой вопрос. Я только что обнаружил, что stackoverflow - плохой клиент чата :)
Норберт Хартл