Дизайн REST API: ответ с кодом 406 или 404, если ресурс недоступен в запрошенном представлении.

У нас есть REST API для загрузки бинарных файлов с сервера.

Запросы выглядят так

GET /documents/e62dd3f6-18b0-4661-92c6-51c7258f9550 HTTP/1.1
Accept: application/octet-stream

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

Но какой ответ должен выдать сервер?

В настоящее время он отвечает

HTTP / 1.1 406 Not Acceptable
Content-Type: application/json
{
  reason: "blabla"
  ...
}

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

Но вопрос в том, как правильно поступить в таких ситуациях?

  • Можно ли отвечать 404 + application/json, хотя был запрошен application/octet-stream
  • Можно ли отвечать 406 + application/json, так как клиент не указал application/json в качестве допустимого типа
  • Должна ли быть расширена спецификация, чтобы клиент использовал q-параметр, например, application/octet-stream, application/json;q=0.1
  • Другие опции?

person Gerald Mücke    schedule 19.09.2018    source источник
comment
В идеальном сценарии REST клиенты будут отправлять все форматы представления, которые он понимает и может понять. т.е. ваш браузер обычно также отправляет не только Accept: text/html, но и набор типов мультимедиа, которые он понимает (или неограниченный набор MIME-типов, то есть вообще image/* или */*). Использование квалификатора для согласования содержимого в целом может быть неплохой идеей.   -  person Roman Vottner    schedule 19.09.2018


Ответы (1)


Если невозможно найти представление для запрошенного ресурса (поскольку он не существует или сервер желает "скрыть" его существование), сервер должен вернуть 404.


Если клиент запрашивает конкретное представление в заголовке Accept и сервер недоступен для предоставления такого представления, сервер может либо:

  • Возвратите 406 вместе со списком доступных представлений. (см. примечание** ниже)
  • Просто игнорируйте заголовок Accept и возвращайте представление ресурса по умолчанию.

См. следующую цитату из RFC 7231, документа, определяющего содержание и семантику протокола HTTP. /1.1 протокол:

Запрос без какого-либо поля заголовка Accept подразумевает, что пользовательский агент примет в ответ любой тип мультимедиа. Если поле заголовка присутствует в запросе и ни одно из доступных представлений для ответа не имеет типа носителя, который указан как приемлемый, исходный сервер может либо принять поле заголовка, отправив ответ 406 (неприемлемо), либо проигнорировать заголовок. поле, обрабатывая ответ так, как будто он не подлежит согласованию содержимого.

Mozilla также рекомендует следующее относительно 406:

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


** Относительно списка доступных представлений см. этот ответ.

person cassiomolin    schedule 19.09.2018
comment
Итак, учитывая, что ресурса на самом деле не существует, сервер должен ответить 404 с телом типа, который выбирает сервер, и просто проигнорировать заголовок Accept, верно? - person Gerald Mücke; 19.09.2018
comment
@ Джеральд Мюке. Да, 404 подходит для этой ситуации. - person cassiomolin; 19.09.2018
comment
@GeraldMücke В зависимости от ваших потребностей вы можете изучить RFC 7807: он определяет простой Форматы документов JSON и XML для описания проблем в HTTP API. Он также определяет типы носителей application/problem+json и application/problem+xml. - person cassiomolin; 19.09.2018