Я работаю с REST API, который находится на сервере, который обрабатывает данные для множества устройств IoT.
Моя задача - выполнить запрос к серверу с помощью API для сбора конкретной информации о производительности указанных устройств.
В одном случае я получаю список доступных устройств и их соответствующие идентификаторы, а затем опрашиваю сервер для получения более подробной информации, используя эти идентификаторы (GUID).
Сервер возвращает 500 Internal Server Error
запрос для одного из этих идентификаторов. В моем приложении выдается исключение, и я не вижу подробностей об ошибке. Если я рассмотрю ответ более подробно с почтальоном , я вижу, что сервер вернул JSON в теле, которое содержит:
errorMessage: "This ID does not exist"
,
Не обращайте внимания на тот факт, что сервер предоставил идентификатор для начала - это отдельная проблема для разработчика.
Должен ли REST API возвращать a, 500 Internal Server Error
чтобы сообщить, что запрос ссылается на несуществующий объект? На мой взгляд, коды ответов HTTP должны строго относиться к состоянию вызова REST, а не к внутренней механике API. Я ожидаю получить 200 OK
ответ с ошибкой и описанием, которые будут принадлежать данному API.
Мне приходит в голову, что есть потенциальная разница в ожидании в зависимости от того, как структурирован вызов REST.
Рассмотрим эти примеры:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
В первом случае идентификатор устройства передается как переменная GET. 404 или 500 будет означать, что path ( /restapi/deviceinfo
) либо не найден, либо привел к ошибке сервера.
Во втором случае идентификатор устройства является частью URL. Я бы лучше понял 404 Not Found
, но все же мог бы поспорить, исходя из того, какие части пути интерпретируются как переменные по сравнению с конечными точками.
Ответы:
Я думаю, что ответ 404 является лучшим семантическим соответствием здесь, потому что ресурс, который вы пытались найти (как представлено URI, использованным для запроса), не был найден. Возврат полезной информации об ошибке в теле является разумным, но не обязательным.
Согласно RFC 2616 определение кода статуса 404:
источник
/questions
, это так/questions/368213
. Эта конечная точка не существует в вашем сценарии. Подумайте об этом так: если вы выполняете GET для / foo / bar, а столбца нет, почему ответ должен быть другим, если / foo существует или нет?How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?
- 400 плохих запросов.Я буду использовать ваши примеры.
Если конечная точка возвращает массив json , лучшим выбором будет
200 OK
пустой массив, если результат не найден.Если конечная точка предназначена для возврата одного результата , мой выбор был бы
404 NOT FOUND
, потому что для меня правильный синтаксис для такого рода конечной точки является:http://example.com/restapi/deviceinfo/123
. Я обычно использую параметр запроса только для фильтрации и когда моя конечная точка возвращает массив.Я думаю, что этот вопрос уже был дан ответ здесь . POST или GET, лучший выбор кажется,
404 NOT FOUND
потому что ресурс123
не был найден.В обоих случаях я не вижу необходимости объяснять причину, по которой запрос не был выполнен. Запрос информации и HTTP-код уже объясняет, почему.
источник
/itms/1234
или/items/12234
.HTTP 404
правильно, потому что сервер понимает, какой ресурс запрашивает клиент, но у него нет этого ресурса.Тот факт, что вы работаете с «REST API», является ключевым. API должен вести себя так, как будто он выполняет REpresentational State Transfer, а не выполняет функцию. (Конечно, термин «REST» приобрел более широкое значение, но вы все равно можете использовать его буквальное значение для достижения хорошего эффекта.) Клиент запросил состояние ресурса, описываемое URL-адресом
http://example.com/restapi/device/123/info
. Строка запроса (/deviceinfo?id=123
) не изменит ситуацию. Сервер знает, что вы просите передать состояние устройства 123, но он не распознает это как известный ресурс. ОтсюдаHTTP 404
.Другие возможные ответы, обсуждаемые здесь, также имеют определенные значения:
HTTP 200
- У нас есть состояние для вас; это в теле ответа.HTTP 204
- У нас есть состояние для вас; это пустоHTTP 400
- Мы не можем сказать, о каком ресурсе вы спрашиваете. Исправьте ваш URL.HTTP 500
- Мы неисправны. Не твоя вина.См. RFC 2616 Sec. 10 соответственно.
источник
Ошибка 5xx обычно используется, чтобы указать, что сервер обнаружил ошибку и не может выполнить запрос. Если сервер принимает запрос, может успешно проанализировать его, а затем выполняет свою работу, это не должно возвращать ошибку 5xx.
Я не уверен, существует ли какое-либо соглашение о том, что возвращать, если запрос не дает результатов. Я видел как то, что вы описываете (200 с телом, содержащим сообщение), так и 404, указывающее, что результаты не были найдены. 200, вероятно, имеет смысл: запрос успешно выполнен, и не было проблем с запросом клиента или во время обработки запроса сервером. Тело может доставить сообщение клиенту.
Я бы рассматривал оба ваших примера (
http://example.com/restapi/deviceinfo?id=123
иhttp://example.com/restapi/device/123/info
) одинаково -123
это параметр. В обоих случаях это разные способы структурирования запроса на получение информации об устройстве для устройства с идентификатором 123.Сначала я бы рассмотрел авторизацию и аутентификацию. Если у пользователя нет соответствующих разрешений, я бы вернул 403 или 401 в зависимости от ситуации. Хотя он называется «Не авторизован», я понимаю, что 401 больше относится к аутентификации, а 403 - к неавторизованному или отказу в доступе. Я бы не стал слишком требователен, если бы вы просто хотели использовать 403 для всех ошибок аутентификации и авторизации.
Затем я бы обработал удостоверение личности. На основании вашего примера это выглядит как числовой идентификатор. Если было предоставлено нечисловое значение, я бы вернул 400. Если параметр мог бы быть допустимым идентификатором устройства, то я бы продолжил обработку. Если бы были другие аргументы, они также были бы проверены здесь. Я ожидаю, что тело ответа будет содержать соответствующую информацию о том, почему запрос был неверным.
Если бы все параметры были действительны, я бы начал обрабатывать запрос. Если система или какая-либо зависимость (база данных, сторонняя служба, другая внутренняя служба) недоступна, я бы вернул код 5xx - 503 будет определенным, но 500 также будет приемлемым. В любом случае я бы вернул тело с дополнительной информацией. Учтите, что если внешняя зависимость сообщает об истечении времени ожидания запроса 408, я бы съел его и вернул клиенту 500, что позволило бы клиенту получить 408, только если время ожидания запроса к моей системе истекло. Если система сможет выполнить запрос, я верну 200 и соответствующий орган.
204 может быть полезен в некоторых случаях, но он не позволяет отправить тело ответа. Особенно в настройке API, отправка тела ответа с информацией, которая может быть передана в механизм ведения журнала или отчетности, в большинстве случаев кажется правильным решением.
Единственный раз, когда 404 будет возвращен, это если сервер не имеет
/deviceinfo
конечной точки или/device/:id/info
конечной точки.Я бы не рассматривал идентификатор, который не найден, таким же, как ресурс, который не найден. Ресурс - это информация об определенном устройстве (в вашем примере). Возврат 404 будет означать, что ресурс (информация об устройстве) не существует. 200 с соответствующим телом означает, что система действительно может предоставить информацию об устройстве. Может быть или не быть устройство с указанным идентификатором.
источник
device: 123; status: not found;
. Тогда я знаю, что запрос сработал, и что API сообщает мне полезную информацию.Ошибка HTTP серии 500 указывает на неисправность сервера. Помимо
501 Not Implemented
и505 HTTP Version Not Supported
, использование этих кодов ошибок подразумевает, что повторная попытка запроса в более позднее время может быть успешной (хотя это только503 Service Unavailable
явно указано). В идеале сервер никогда не должен генерировать один из этих кодов, хотя невозможность написать безошибочное программное обеспечение и обеспечить сервер бесконечными ресурсами означает, что они вам понадобятся время от времени.Для результата «объект не существует» вы, вероятно, должны вернуть либо
404 Not Found
(когда запрос предназначен для объекта по имени), либо200 Success
с пустым телом результата (при поиске объекта по атрибутам).204 No Content
выглядит заманчиво, но я бы использовал его только для ситуаций, когда отсутствие тела ответа является ожидаемым результатом.источник
Как клиент вашего API, когда я делаю один из этих вызовов:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
Я рассчитываю получить (представление)
DeviceInfo
объект (или какой-то конкретный тип в любом случае, будь то формальный тип или просто что-то, соответствующее документированному соглашению об «типе утки»). Я хочу, чтобы200
статус означал, что я действительно получил его, и я могу пойти дальше и использовать его.Для API REST я считаю коды состояния 400 и 500 чем-то вроде исключений. Вы используете их, чтобы указать, когда вы не можете вернуть «нормальный» ответ на полученный вами запрос, поэтому клиенту нужно будет сделать что-то исключительное, а не обработать информацию, которую он ожидал получить.
Это означает, что в качестве потребителя API я могу использовать какую-то функцию check-rest-call, которая получает ответ или выдает исключение. Замечательно; моя обычная логика может быть прямым кодом, и я могу организовать обработку ошибок так же, как в локальном коде. Неожиданные 404 будут проявляться как исключения «ресурс не найден», и мне вообще ничего не нужно делать, а не как ошибки «отсутствующего атрибута», когда я позже обработаю их,
{ errorMessage: "Device 123 not found" }
как если бы это былDeviceInfo
объект.Если причина того, что конечная точка
http://example.com/restapi/deviceinfo
будет найдена, и это только ,id=123
что это не так , и так вернуться 200 с сообщением об ошибке в теле, то вы создаете точно такой же вид проблем интерфейса как функции C , которые могут возвращать либо исправить результат или код ошибки, или методы, которые указывают на проблемы путем произвольного возвратаnull
, Пользователю вашего интерфейса гораздо приятнее, когда ошибки выводятся через «отдельный» канал от регулярных возвратов. Это применимо и здесь, даже если ответы HTTP 200, 404 и 500 являются одним и тем же каналом с точки зрения низкого уровня. Они стандартизированы и их легко отличить друг от друга, поэтому моя клиентская среда REST может легко включить эти статусы, чтобы превратить их в правильные структуры на моем языке; чтобы сделать то же самое со слоем JSON (где вы всегда говорите 200 и даете мне либоDeviceInfo
сообщение об ошибке, либо сообщение об ошибке), мне нужно вложить некоторые знания о схемах JSON, которые вы используете.Поэтому используйте только 200, когда вы можете вернуть допустимое значение ожидаемого типа (поэтому
http://example.com/restapi/search-devices?colour=blue
можно возвращать 200 с пустым массивом, если нет синих устройств; пустой массив является допустимым массивом, а разумный ответ на запрос "I хотел бы детали всех синих устройств "). Если вы не можете, используйте наиболее подходящий код состояния, отличный от 200. Несмотря на то, что «устройство 123 не существует» является правильным ответом на «предоставить мне данные устройства 123» и не является ошибкой для сервера , это исключение для ожидания клиента того, что он получит ответDeviceInfo
и должен не сообщайте как нормальный ответ «вот что вы просили».источник
Вы можете использовать ошибку 422 Unprocessable Entity, чтобы отличить ее от 404 not found . 422 означает, что сервер понимает запрос, но не может дать правильный ответ. Я использую этот код в похожих ситуациях.
источник
Ошибка 500 обычно указывает, что запрос потерпел крах программы на стороне сервера; в корпоративной среде эти ошибки рассматриваются как яйцо на лице, и их избегают.
Ошибка 4xx должна сигнализировать программисту, что конечная точка API (ресурс) не существует. Следовательно, как только соответствующая конечная точка достигнута, любая обработка ошибок с этого момента является обязанностью программиста API, которая должна выполняться корректно, то есть с сообщением об ошибке ответа 200.
источник
Хотя w3 отмечает, что 404 используется, когда никакой другой ответ не применим , разве это не подходит для ответа 204 (без контента)? Запрос был действителен с точки зрения обработки, и сервер обработал запрос и дал результат. Это успех, который опирается на ответы 2xx. Контента для этого конкретного запроса не было, поэтому 204 сообщает пользователю, что с его запросом все в порядке, но там ничего нет.
Вы также можете сделать слабый случай, что 409 (конфликт) является подходящим ответом. Хотя 409 чаще всего используется для POST, он говорит
возможно, несуществование запрошенного идентификатора является конфликтом здесь, и возвращение в сообщении, что такого идентификатора не существует в системе, является достаточной информацией для пользователя, чтобы распознать и исправить конфликт.
источник
Другие ответы покрывают это, но я просто хотел указать, что ошибка 500-й серии означает «Я испортил». В этом случае «I» означает API, поэтому необработанная ошибка сервера или подобное. Ошибка 400-й серии означает «вы все испортили» - вызывающий API отправил что-то неверное.
источник
Другие пользователи предоставили правильные ответы на вопрос, что делать, если вы хотите пройтись по книге.
Однако я хотел бы предложить, чтобы вы слишком много читали о RESTfulness и были абсолютно кошерными по отношению к ней.
REST является капризным протоколом, потому что, если вы хотите следовать книге во время ее использования, то он заставляет и клиента, и сервер быть собранным, имея конкретные знания о том, что они общаются через REST, поэтому по сути, конкретный протокол связи является Использовать нельзя абстрагироваться.
Существует другой подход: полностью избегать RESTfulness и использовать его просто как протокол связи и ничего больше. Это означает, что единственными ответами, которые необходимо вернуть, являются «HTTP 200 OK» и «HTTP 500 Internal Server Error», поскольку в отношении протокола связи любая попытка установить связь может иметь только два результата: либо запрос был успешным доставлено на сервер или нет.
То, что происходит после доставки, не является делом протокола связи. Таким образом, как только сервер успешно принял запрос и начал его обрабатывать, может возникнуть много ошибок, но все это ошибки, относящиеся к конкретному приложению, о которых не нужно знать ни о каком протоколе связи. Они должны быть переданы в полезной нагрузке ответа, который выглядит совершенно успешным, насколько известно протоколу связи.
Итак, суть в том, что я бы порекомендовал вернуть «HTTP 200 OK», и в полезной нагрузке ответа («тело содержимого ответа» на языке HTTP) есть прикладной код ошибки, который говорит «ID not found» или что-то еще.
источник