Представьте себе API, чтобы определить, выбрал ли человек свое духовное животное. У них может быть только ноль или одно духовное животное.
В настоящее время:
/person/{id}/selectedSpiritAnimal
когда они выбрали животное возвращает http 200 и {selectedAnimal:mole}
но когда у них нет выбора, возвращается http 404.
Это делает мое духовное животное несчастным, поскольку мы представляем действительную проблему домена - еще не выбрав духовное животное - как ошибку HTTP.
Кроме того, как бизнес, а именно Sprit-Animal-Hampers-R-us, мы хотим знать, когда у кого-то нет выбора, поэтому мы можем подсказать им.
Какой лучший ответ здесь:
HTTP 200 и {selectedAnimal:null}
или даже более явно
HTTP 200 и {selectedAnimal:null, spiritAnimalSelected: false}
Или лучше вернуть 404? Так как this image has not yet been uploaded
при просмотре изображения онлайн было бы 404. this person has not selected a spirit animal
может быть 404
Этот вопрос был предложен как дубликат, но этот вопрос касается запрашиваемого в противном случае действительного URL-адреса, когда приложение настроено так, чтобы не допустить изменения, которое представляет этот URL-адрес.
В то время как здесь я смотрю на то, как каждый представляет ресурс, где отсутствие ресурса имеет смысл. Т.е. клиент может запросить URL-адрес, и ответом является то, что вы успешно запросили ресурс, который представляет отсутствие объекта.
Так что это не «бизнес-логика», а скорее обстоятельство, при котором отсутствие вещи имеет значение (возможно, многие мои коллеги утверждают, что 404 по-прежнему верен), но я не уверен, как сопоставить это с спекуляция
Очень сложно подобрать ответ. Я передумал несколько раз за разговор здесь и тот, который продолжается на работе.
Дело в том, что для меня это решается тем, что в спецификации говорится, что 4xx - это ошибка клиента . В этом случае клиенту было сказано ожидать ответа от URL выбранного selectedSpiritAnimal, поэтому он не допустил ошибку.
Консенсус среди моих коллег в том, что это признак плохого дизайна API
Вероятно, было бы лучше, если бы мы просто запросили / person / {id}, и это возвращает набор отношений ссылки для человека ... тогда, если вам не дают ссылку / selectedSpiritAnimal (когда у человека нет выбора), но вы в любом случае, называть это 404 имеет смысл. Или что вы реализуете частичные ответы и позволяете / person / {id} возвращать более полный документ, если клиент не запрашивает подмножество данных
Ответы:
Коды HTTP 4xx, вероятно, не являются правильным выбором для этого сценария. Вы утверждаете, что наличие животных с нулевым духом является действительным состоянием, и маршрут API
person/{id}/selectedSpiritAnimal
будет учитывать, есть ли у человекаid
такой или нет.Ответы HTTP 4xx зарезервированы для ситуации, когда клиент сделал что-то неправильное в запросе (см . Архив оригинальной спецификации w3 ). Но клиент делает правильный запрос, независимо от того,
id
есть у человека духовное животное или нет .Поэтому я склоняюсь ко вторым решениям, используя правильно отформатированное тело JSON в ответе и код HTTP 2xx.
Теперь, если вы получаете такой запрос, и оказывается, что человек
id
не существует, код 4xx имеет больше смысла.источник
cases in which the client seems to have erred
, а с другой - 404The server has not found anything matching the Request-URI
. Вы можете запросить что-то, что не существует ошибки клиента. Я понимаю, что человек не существует против подпора не существует, но это может быть указано в ответном сообщении. 204 также представляется уместным, поскольку сущность существует, но не имеет содержимого для подчиненного свойства.Позвольте мне представить вам модель зрелости Ричардсона .
Ваша проблема в том, что вы представляете два ресурса как один, где у вас должно быть два ресурса, связь между которыми обозначена гипермедиа. Использование гипермедиа для описания отношений - это великолепный уровень 3 отдыха.
Ваш человек должен жить под URI,
/person/{id}
а животное должно жить под/spiritanimal/{id}
. Человек должен указать, что у него есть духовное животное, используя ссылку на животное.Представим себе человека по имени Боб, у которого есть идентификатор 123 и духовное животное Единорог.
GET /person/123
вернется;
Теперь любой, кто читает человека 123, будет знать, что у него есть духовное животное, и у него есть URI, где он может получить больше информации о нем.
GET /spitiranimal/789
может вернуться
Теперь давайте представим человека по имени Фред, у которого id 456 и у которого нет духовного животного.
GET /person/456
вернется;
Теперь любой, кто читает человека 456, будет знать, что у него нет духовного животного, поскольку нет ссылки. Нет необходимости использовать какой-либо код состояния HTTP для представления отсутствия связи.
источник
Это подходящий URL для получения духовных животных; следовательно, ошибка 404 неуместна. 404 предназначен для представления технической проблемы, а не логической проблемы.
Соответствующее решение - вернуть http 200 и
{"selectedAnimal": null}
У вас должен быть отдельный веб-метод,
/person/{id}/hasSelectedSpiritAnimal
который возвращается{"isSpiritAnimalSelected": false}
. За кулисами он может или не может делать одни и те же вызовы методов, просто возвращая false, если ноль, но это решать, а не код потребления.Лучше избегать объединения отдельных запросов в один веб-метод без веской причины для этого, даже если запросы тесно связаны.
источник
When you said "the spirit animal is not currently on file", it seemed quite similar to me to "there is no content"
Нет контента означает, что нет контента . т.е. он возвращает "". Эти двое совсем не похожи. «Духовное животное в настоящее время отсутствует в архиве» сильно отличается от «».То, что представляет ваша конечная точка, не просто животное; это животное или его отсутствие. Это значение лучше всего представляется через
Optional
/Maybe
/Nullable
/ и т. Д.Таким образом, допустимые значения (как в 200 ОК) могут быть:
{'animal': <some animal>, 'selected': true}
{'animal': null, 'selected': false}
Я мог бы представить, что этот
DELETE
метод при применении к конечной точке может снова установить'selected'
значениеfalse
, то есть сбросить выбранное животное.Вы можете, конечно, опустить
'selected'
ключ здесь, это показано только для ясности; Строка противnull
достаточно для различия.источник
Вы должны использовать 404.
Поскольку вы создаете интерфейс программирования, а не интерфейс человека, текст 404 является необязательным.
Я предпочитаю это, потому что я предпочитаю стандартные протоколы, насколько это возможно. HTTP имеет способ представить несуществование, и это то, что я бы использовал.
РЕДАКТИРОВАТЬ: Предположим, вы добавили функцию, где пользователи могли выбирать, делиться ли они своими духовными животными, а кто-то не делился ею. Вы бы вернули 200 ОК
null
или 200 ОК"Unauthorized
? Или вы бы использовали стандартный 401 Unauthorized / 403 Forbidden? Это похоже на прямую аналогию с тем, чтобы не выбирать никого в первую очередь.В качестве альтернативы, если вы хотите использовать 200 OK + JSON, вы должны вернуться
null
.Держите вещи в чистоте. Создайте больше упаковки только в случае необходимости.
источник
null
(не имеет значения). Это отличается от того, что клиент запрашивает что-то, для чего не существует слота для хранения значения. Вы не предлагаете бросатьAttributeError
в Python, когда значение оказываетсяNone
; это сделало бы интерфейс непрактичным и излишне сложным для работы. Более прагматично: многие клиентские API-интерфейсы HTTP могут преобразовать 404 в стандартный механизм обработки ошибок языка (код ошибки, исключение, тип ошибки), что означает, что вам придется подавлять постороннюю ошибку./person/{id}/selectedSpritAnimal
Е. Наблюдаете опечаткуSprit
)./person/{id}/isSpiritAnimalSelected
который сообщит клиенту, был ли он выбран. Мне кажется, это тот же классический пример тестирования, существует ли файл перед его чтением. Просто прочитайте файл и обработайте ошибку ENOENT, если она будет выдана./person/{id}/selectedSpiritAnimal
предполагается использовать, даже если духовное животное не существует. Это означает, что HTTP 4xx неверен, когда используется в таком случае. Op также правильно утверждает, что это может быть запахом плохого дизайна API.