Ошибка API REST возвращает хорошие практики [закрыто]

623

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

Сейчас я добавляю несколько случаев ошибок, например, клиент пытается добавить новый ресурс, но превысил свою квоту хранилища. Я уже обрабатываю определенные случаи ошибок с кодами состояния HTTP (401 для аутентификации, 403 для авторизации и 404 для простых неверных URI запросов). Я просмотрел благословенные коды ошибок HTTP, но ни один из диапазонов 400-417, похоже, не подходит для сообщения об ошибках приложения. Поэтому сначала я хотел вернуть ошибку моего приложения с 200 OK и определенной полезной нагрузкой XML (т.е. заплатите нам больше, и вы получите необходимое хранилище!), Но я перестал думать об этом, и это кажется мыльным (/ пожимает плечами в ужасе). Кроме того, мне кажется, что я делю ответы об ошибках на отдельные случаи, так как некоторые из них управляются кодом состояния http, а другие - содержимым.

Так, каковы отраслевые рекомендации? Хорошая практика (пожалуйста, объясните почему!), А также, от клиента, что обработка ошибок в REST API облегчает жизнь клиентскому коду?

Ремус Русану
источник
7
Просто чтобы уточнить: меня не очень интересует, какой конкретный код состояния HTTP нужно возвращать, но является ли хорошей практикой REST объединение ошибок полезной нагрузки с кодами состояния HTTP или лучше полагаться исключительно на полезную нагрузку.
Ремус Русану
3
REST API Design Handbook достаточно хорошо освещает эту тему.
Ремус Русану
12
Вопрос не спрашивает мнение, но для руководства / рекомендаций и должен быть вновь открыт и использоваться в качестве ссылки. Какой смысл закрывать в 2016 году вопрос, который был создан в 2009 году, имеет 400+ голосов и ни один из существующих ответов не основан на мнениях
Майкл
4
Большинство не упомянуло, но использование кодов ошибок HTTP может привести к проблемам, связанным с основной причиной проблемы. HTTP является транспортным протоколом, и 404 должен указывать, что возникла проблема с URL на транспортном уровне (например, неверный путь). Если приложение не может найти набор данных по его идентификатору, это ошибка уровня приложения (а не ошибка транспортного уровня), и 404, как предлагают пользователи спокойного http-кода состояния, может привести к неверному выводу. Как правило, мне не нравится смешивание транспортного и прикладного уровней при использовании кодов состояния.
SCI

Ответы:

220

Поэтому сначала я хотел вернуть ошибку моего приложения с 200 OK и определенной полезной нагрузкой XML (т.е. заплатите нам больше, и вы получите необходимое хранилище!), Но я перестал думать об этом, и это кажется мыльным (/ пожимает плечами в ужасе).

Я бы не вернул 200, если в запросе не было ничего плохого. Из RFC2616 200 означает «запрос успешно выполнен».

Если квота хранилища клиента была превышена (по какой-либо причине), я бы вернул 403 (Запрещено):

Сервер понял запрос, но отказывается его выполнить. Авторизация не поможет и запрос НЕ ДОЛЖЕН повторяться. Если метод запроса не был HEAD и сервер желает обнародовать, почему запрос не был выполнен, он ДОЛЖЕН описать причину отказа в объекте. Если сервер не желает предоставлять эту информацию клиенту, вместо него можно использовать код состояния 404 (не найден).

Это говорит клиенту, что запрос был в порядке, но что он потерпел неудачу (что 200 не делает). Это также дает вам возможность объяснить проблему (и ее решение) в теле ответа.

Какие еще конкретные ошибки вы имели в виду?

Богатая Аподака
источник
6
Должен ли я включить мое подробное сообщение об ошибке в теле, т.е. код XML / пара строк? Как клиенты лучше всего справляются с этим? Например, я знаю, что клиенты на основе C # WebRequest будут выдавать «Bad Request» или «Forbidden» и не будут давать тело ответа.
Ремус Русану
18
Тело 403 «должно» содержать детали ошибки. Готов ли клиент использовать информацию - это другая история. Наиболее целесообразно, чтобы этот формат совпадал с форматом для всех других полезных нагрузок (например, XML, JSON).
Богатая Аподака
1
... и если детали не возвращаются в 403, вместо этого можно использовать 404 "может" (хотя для меня это не лучший вариант).
Богатая Аподака
6
Опция 404 предназначена для случая, когда 403 может раскрыть подробности о приложении, о которых не хотят, чтобы неавторизованные пользователи знали о них - например, если пользователь без прав администратора переходит по URL-адресу только для администратора, вы, возможно, не хотите, чтобы этот пользователь знать, что это действительный URL для администраторов и т. д. В этом случае, однако, 403 полностью подходит.
Грег Кэмпбелл
16
Я чувствую, что это довольно бесполезный ответ. Я бы подумал, что более важный аспект касается того, должны ли статусы использоваться исключительно, или должна ли информация об ошибке возвращаться в полезной нагрузке, или и то, и другое, и т. Д. И затем КАК эта информация должна быть добавлена ​​в полезную нагрузку. Определенный используемый статус оттачивает только один конкретный аспект вопроса.
Манахи
584

Отличный ресурс, чтобы выбрать правильный код ошибки HTTP для вашего API: http://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

Отрывок из статьи:

Когда начать:

введите описание изображения здесь

2XX / 3XX:

введите описание изображения здесь

4XX:

введите описание изображения здесь

5XX:

введите описание изображения здесь

Омар Али
источник
1
422 Это специально расширение WebDAV. Я думаю, что это не должно быть здесь.
Марио
@Mario В Ruby on Rails API идиоматично возвращать 422 в ответ на условия, указанные здесь. Много хорошего уже следовало этому подходу. Что бы вы заменили использование 422 для?
Келси Ханнан
обычный старый 400
Andbdrew
Спасибо. Что значит «Ты в ярости выходишь из Интернета?»?
RoutesMaps.com
@ Crimean.us google.com/search?q=define+rage-quit
Омар Али,
87

Основной выбор заключается в том, хотите ли вы рассматривать код состояния HTTP как часть вашего REST API или нет.

Оба способа работают нормально. Я согласен, что, строго говоря, одна из идей REST заключается в том, что вы должны использовать код статуса HTTP как часть вашего API (вернуть 200 или 201 для успешной операции и 4xx или 5xx в зависимости от различных случаев ошибки.) Однако ОТСУТСТВУЕТ полиция. Ты можешь делать, что хочешь. Я видел гораздо более вопиющие API без REST, называемые RESTful.

На данный момент (август 2015 г.) я рекомендую использовать код статуса HTTP как часть вашего API. Теперь намного проще увидеть код возврата при использовании фреймворков, чем это было в прошлом. В частности, теперь легче увидеть случай возврата, не связанный с 200, и массу ответов, не связанных с 200, чем это было в прошлом.

Код статуса HTTP является частью вашего API

  1. Вам нужно будет тщательно выбрать коды 4xx, которые соответствуют вашим условиям ошибки. В качестве полезной нагрузки можно добавить сообщение отдыха, XML или текстовое сообщение, которое включает субкод и описательный комментарий.

  2. Клиенты должны будут использовать программную среду, которая позволяет им получить код состояния уровня HTTP. Обычно выполнимый, не всегда прямой.

  3. Клиенты должны будут различать коды состояния HTTP, которые указывают на ошибку связи, и ваши собственные коды состояния, которые указывают на проблему на уровне приложения.

Код статуса HTTP НЕ является частью вашего API

  1. Код состояния HTTP всегда будет равен 200, если ваше приложение получило запрос и затем ответило (как в случае успеха, так и в случае ошибки)

  2. ВСЕ ваши ответы должны содержать информацию «конверта» или «заголовка». Типично что-то вроде:

    envelope_ver: 1.0
    статус: # используйте любые коды, которые вам нравятся. Зарезервируйте код для успеха.
    msg: "ok" # Строка человека, которая отражает код. Полезно для отладки.
    data: ... # Данные ответа, если есть.
  3. Этот метод может быть проще для клиентов, так как статус ответа всегда находится в одном и том же месте (не требуются субкоды), нет ограничений на коды, нет необходимости извлекать код состояния уровня HTTP.

Вот пост с похожей идеей: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Главные проблемы:

  1. Обязательно укажите номера версий, чтобы позже вы могли изменить семантику API, если это необходимо.

  2. Документ...

Ларри К
источник
8
Ty. Вариант 2 выглядит как SOAP в одежде для отдыха ...
Remus Rusanu
138
Нет, туннелирование всего через 200 не совсем успокаивает. Это мешает посредникам понять результат операции, которая уничтожит любую форму кэширования, скрывает семантику операции и навязывает понимание содержимого сообщения для обработки ошибки, нарушая ограничение автономных сообщений.
SerialSeb
13
Возвращать подробности об ошибке с 200, возможно, не RESTful, но, тем не менее, это полезный ответ (если вы игнорируете замечание «Оба пути успокаивающие») ... Большим моментом может быть то, что RESTful API может быть не лучшим вариантом для ОП.
МБ.
3
Кажется, существует общее понимание того, что вы можете делать все, что вы хотите с протоколом HTTP и при этом быть «RESTy», это неверно. Используйте протокол для написанного, это одна из основных идей REST. Таким образом, код состояния должен быть частью вашего протокола.
Ариэль М.
Смысл кодов состояния заключается в предоставлении общего языка понимания между различными языками программирования, средами и подходами. Значения кода состояния близки к универсальным: ваше собственное тело - которое по своей природе добавляет сложности с помощью пользовательского синтаксиса, который должны выучить пользователи API, - нет.
Келси Ханнан
40

Помните, что кодов состояния больше, чем определено в RFC HTTP / 1.1, реестр IANA находится по адресу http://www.iana.org/assignments/http-status-codes . Для случая, когда вы упомянули код состояния 507 звучит правильно.

Джулиан Решке
источник
3
Хм, хотя с первого взгляда «507 Недостаточно памяти» кажется подходящим, я бы с осторожностью использовал его, поскольку он предназначен как (довольно специфическое) расширение WebDAV, а не как правило «эй, у вас недостаточно места» исключение. Тем не менее, я полагаю, вы могли бы использовать это.
Макс
1
Нет, это совсем не WebDAV. Существует причина, по которой существует реестр для кодов состояния HTTP.
Джулиан Решке
26
Я не согласен с 507этой целью. Моя интерпретация 507заключается в том, что на сервере недостаточно места, а не в учетной записи.
Патрик
12
Я согласен с Патриком. 5xxошибки для ошибок, связанных с сервером.
Шон
10
418: «Я - чайник», подразумевая, что место для хранения слишком мало (как чайник - мало), а не велико и, следовательно, не хватает места.
Стив Конвес
22

Как указывали другие, наличие объекта ответа в коде ошибки вполне допустимо.

Помните, что ошибки 5xx относятся к серверной части, иначе клиент не может ничего изменить в своем запросе для выполнения запроса. Если квота клиента превышена, это определенно не ошибка сервера, поэтому следует избегать 5xx.

SerialSeb
источник
Я бы не согласился. Превышение квоты будет ошибкой сервера (5xx), потому что: запрос клиента действителен и будет выполнен успешно, если под квотой исключено 400 серий.
mikek3332002
4
Но сервер не сделал ничего плохого.
Чарли Шлиссер
19

Есть два вида ошибок. Ошибки приложения и ошибки HTTP. Ошибки HTTP просто для того, чтобы ваш обработчик AJAX знал, что все прошло хорошо и не должен использоваться ни для чего другого.

5xx Ошибка сервера

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx Успех

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Однако то, как вы разрабатываете ошибки приложения, зависит от вас. Переполнение стека, например , посылает объект с response, dataи messageсвойствами. Я полагаю, что ответ содержит trueили falseуказывает, была ли операция успешной (обычно для операций записи). Данные содержат полезную нагрузку (обычно для операций чтения), а сообщение содержит любые дополнительные метаданные или полезные сообщения (например, сообщения об ошибках, когда responseесть false).

aleemb
источник
2
400 также полезно для указания проблемы в клиентском приложении.
Дольмен
19

Я знаю, что это очень поздно для вечеринки, но теперь, в 2013 году, у нас есть несколько типов носителей, чтобы покрыть обработку ошибок обычным распределенным (RESTful) способом. См. «Vnd.error», application / vnd.error + json ( https://github.com/blongden/vnd.error ) и «Сведения о проблеме для HTTP API», application / problem + json ( https: // tools. ietf.org/html/draft-nottingham-http-problem-05 ).

Йорн Вильдт
источник
2
Спасибо за ссылки. draft-nottingham-http-problem теперь является предлагаемым стандартом: datatracker.ietf.org/doc/rfc7807
seanf
9

Согласовано. Основная философия REST - использование веб-инфраструктуры. Коды состояния HTTP - это структура обмена сообщениями, которая позволяет сторонам связываться друг с другом без увеличения полезной нагрузки HTTP. В них уже созданы универсальные коды, передающие статус ответа, и поэтому, чтобы быть действительно RESTful, приложения должны использовать эту платформу для передачи статуса ответа.

Отправка ответа об ошибке в конверте HTTP 200 вводит в заблуждение и вынуждает клиента (пользователя API) анализировать сообщение, скорее всего, нестандартным или закрытым способом. Это также неэффективно - вы будете заставлять своих клиентов каждый раз анализировать полезную нагрузку HTTP, чтобы понять «реальный» статус ответа. Это увеличивает обработку, увеличивает задержку и создает среду для ошибок клиента.

Kingz
источник
3
Независимо от того, был ли у вас успешный ответ или отказ, вы, скорее всего, будете анализировать ответ. Если это ошибка, вы хотите проанализировать ее, чтобы получить сообщение об ошибке. Ответы об ошибках, как правило, невелики и быстро разбираются. Я не думаю, что мы должны беспокоиться о попытках оптимизации, чтобы избежать анализа ошибок. Вы просто выбросили бы ответ об ошибке, не анализируя его? Неразумно по моему мнению.
AgilePro
3
Если вы получите 200 OK, вы можете также не анализировать его, в зависимости от ваших бизнес-правил. Дело не в том, разбираем ли мы его постоянно или нет. Дело в намерении - в чем смысл 200 ОК? Вы наносите ущерб намерению, отправляя сообщения об ошибках, завернутые в 200 OK.
Кингз
1
"Каково намерение 200 ОК?" - указание на успех транспортного уровня. Запрос был успешно получен и получен ответ, возникла просто проблема, связанная с приложением, не имеющая ничего общего с HTTP. +++ Иначе говоря: отправка 404 в мир REST означает, что что- то не найдено, возможно, URL-адрес неверный, ресурс, подлежащий обработке, или что-то еще не найдено. Без разбора сообщения вы не сможете. ИМХО ОТДЫХ это просто смешение слоев.
Maaartinus
Слияние - это норма. Он предоставляет вам синтаксис для решения, который соответствует вашей линии рассуждений, и позволяет вам сосредоточиться на бизнес-уровне. Согласившись на более поздние сообщения о статусе транспорта - именно это и было целью в первую очередь - REST не был изобретен / предложен одновременно с HTTP - он пришел позже и просто решил использовать существующую инфраструктуру для представления данных о ГОСУДАРСТВАХ и их ИЗМЕНЕНИЯХ.
Кингз
5

Пожалуйста, придерживайтесь семантики протокола. Используйте 2xx для успешных ответов и 4xx, 5xx для ответов об ошибках - будь то ваши бизнес-исключения или другие. Если бы 2xx для любого ответа был предполагаемым вариантом использования в протоколе, у них не было бы других кодов состояния в первую очередь.

rahil008
источник
3

Не забывайте об ошибках 5xx, а также об ошибках приложений.

В этом случае, как насчет 409 (конфликт)? Это предполагает, что пользователь может решить проблему, удалив сохраненные ресурсы.

В противном случае 507 (не совсем стандарт) также может работать. Я бы не использовал 200, если вы не используете 200 для ошибок в целом.

Кэти Ван Стоун
источник
-2

Если клиентская квота превышена, это ошибка сервера, избегайте 5xx в этом случае.

фиксированная рента
источник
3
Зачем избегать ошибок серии 5xx, если они связаны с ошибками сервера?
mikek3332002
7
«Превышена квота клиента» - это не ошибка сервера imho, это ограничение клиента и должно быть меньше 4xx.
MyGGaN