REST API错误返回良好做法[关闭]


622

我正在寻找有关从REST API返回错误的良好实践指南。我正在开发一个新的API,所以我现在可以朝任何方向发展。目前,我的内容类型是XML,但我计划将来支持JSON。

我现在添加了一些错误情况,例如,某个客户端尝试添加新资源,但已超出其存储配额。我已经在使用HTTP状态代码处理某些错误情况(身份验证为401,身份验证为403,普通错误请求URI为404)。我查看了受祝福的HTTP错误代码,但400-417范围似乎都不适合报告应用程序特定的错误。因此,起初我很想以200 OK和特定的XML有效负载返回我的应用程序错误(即,向我们支付更多,您将获得所需的存储空间!),但我停下来考虑一下,而且似乎很肥皂水(/耸了耸肩)。除此之外,感觉像是将错误响应分为不同的情况,因为有些是http状态代码驱动的,而另一些则是内容驱动的。

那么行业的建议是什么?良好做法(请解释原因!),以及从客户端pov看,REST API中的哪种错误处理使客户端代码的工作变得更轻松?


7
只是要澄清一下:我对返回哪个特定的HTTP状态代码不是很感兴趣,但是是将负载错误与HTTP状态代码结合起来的良好REST做法还是仅依靠负载更好?
Remus Rusanu

3
REST API设计手册很好地涵盖了该主题。
Remus Rusanu 2012年

12
该问题并不是要征求意见,而是要提供指导/建议,应该重新打开并用作参考。什么是点到接近2016年的问题,这是创建于2009年,有400点多票,并根据意见现有的答案没有人
迈克尔Freidgeim

4
大多数都没有提到,但是使用HTTP错误代码可能导致出现问题的主要原因。HTTP是传输协议,并且404应该指示URL传输级别存在问题(例如,错误的路径)。如果应用程序无法通过其ID查找数据集,则这是应用程序级错误(不是传输级错误),并且静态的HTTP状态代码用户建议使用404可能导致错误的结论。通常,我不喜欢使用状态码来混合传输层和应用程序层。
SCI

Answers:


220

因此,起初我很想以200 OK和特定的XML有效负载返回我的应用程序错误(即,向我们支付更多,您将获得所需的存储空间!),但我停下来考虑一下,而且似乎很肥皂水(/耸了耸肩)。

除非请求确实没有错,否则我不会返回200。从RFC2616开始,200表示“请求已成功”。

如果超过了客户端的存储配额(无论出于何种原因),我将返回403(禁止访问):

服务器理解了该请求,但拒绝执行该请求。授权将无济于事,不应重复该请求。如果请求方法不是HEAD,并且服务器希望公开为什么未满足请求,则应在实体中描述拒绝的原因。如果服务器不希望将此信息提供给客户端,则可以改用状态代码404(未找到)。

这告诉客户端该请求是可以的,但是失败了(200不能执行此操作)。这也使您有机会在响应正文中解释问题(及其解决方案)。

您还要考虑其他哪些特定的错误条件?


6
我是否应该在正文中包含详细的错误消息,即。一个XML代码/字符串对?客户如何最好地应对呢?例如,我知道基于C#WebRequest的客户端会抛出“ Bad Request”或“ Forbidden”,而不给出响应主体。
Remus Rusanu 2009年

18
403的主体“应”包含错误的详细信息。客户是否准备好利用信息是另一回事。使这种格式与所有其他有效负载(例如XML,JSON)的格式相同是最有意义的。
Rich Apodaca,2009年

1
...,如果未在403中返回详细信息,则使用404“可以”代替(尽管这对我来说似乎不是最好的选择)。
Rich Apodaca,2009年

6
404选项用于以下情况:403可能会泄露您不希望未经授权的用户知道的应用程序的详细信息-例如,如果非管理用户访问的是仅管理员的URL,则您可能不希望该用户知道这是管理员等的有效URL。在这种情况下,403非常合适。
格雷格·坎贝尔,

16
我觉得这是一个毫无用处的答案。我本来以为更重要的方面是关于是否应仅使用状态,或者是否应在有效负载中返回错误信息,或两者都应等等。然后,如何将信息添加到有效负载中。使用的特定状态仅针对问题的一个特定方面。
Manachi

584

为您的API选择正确的HTTP错误代码的绝佳资源:http : //www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

文章摘录:

从哪儿开始:

在此处输入图片说明

2XX / 3XX:

在此处输入图片说明

4XX:

在此处输入图片说明

5XX:

在此处输入图片说明


1
422特别是WebDAV扩展。我认为那不应该在这里。
马里奥(Mario)

@Mario在Ruby on Rails API中很常见,它会根据此处指定的条件返回422。遵循该方法已经有很多好处。您将用什么代替422?
Kelsey Hannan '18

常规的旧400
Andbdrew

谢谢。什么是“您正在愤怒地退出互联网?”?
RoutesMaps.com


87

主要选择是您是否要将HTTP状态代码视为REST API的一部分。

两种方式都可以正常工作。我同意,严格来说,REST的想法之一是您应该将HTTP状态代码用作API的一部分(成功操作返回200或201,并根据各种错误情况返回4xx或5xx。)但是,没有REST警察。你可以做你想做的。我已经看到了更令人震惊的非REST API被称为“ RESTful”。

此时(2015年8月),我建议您将HTTP状态代码用作API的一部分。现在,使用框架时比过去更容易看到返回代码。特别是,与过去相比,现在更容易看到非200的返回案例和非200的响应正文。

HTTP状态代码是您的api的一部分

  1. 您将需要仔细选择适合您的错误条件的4xx代码。您可以包括rest,xml或纯文本消息作为有效负载,其中包括子代码和描述性注释。

  2. 客户端将需要使用使他们能够获得HTTP级状态代码的软件框架。通常可行,但并不总是直截了当。

  3. 客户端必须区分表示通信错误的HTTP状态代码和表示应用程序级问题的您自己的状态代码。

HTTP状态代码不属于您的api

  1. 如果您的应用收到请求然后响应,则HTTP状态代码将始终为200(成功和错误情况)

  2. 您的所有回复都应包含“信封”或“标题”信息。通常是这样的:

    信封版本:1.0
    状态:#使用您喜欢的任何代码。保留成功代码。
    msg:“ ok”#反映代码的人为字符串。对调试有用。
    数据:...#响应的数据(如果有)。
  3. 对于客户端,此方法可能更容易,因为响应的状态始终在同一位置(不需要子代码),没有代码限制,也不需要获取HTTP级别的状态代码。

这是具有类似想法的帖子:http: //yuiblog.com/blog/2008/10/15/datatable-260-part-one/

主要问题:

  1. 确保包含版本号,以便以后可以根据需要更改api的语义。

  2. 文献...


8
泰 选项2看起来像是穿着便服的肥皂……
Remus Rusanu

138
不,通过200隧道传输所有内容并不是一件容易的事。它阻止中介机构理解操作的结果,该操作的结果将终止任何形式的缓存,隐藏操作的语义,并强加理解消息的内容以处理错误,从而破坏了独立消息的约束。
SerialSeb

13
返回带有200的错误详细信息可能不是RESTful的,但是,这仍然是一个有用的答案(如果您忽略“两种方式都很安静”的话)...更大的意义可能是RESTful API可能不是最佳选择OP。
MB。

3
似乎有一个大致的了解,即可以使用HTTP协议执行任何操作,并且仍然保持“ RESTy”状态,这是错误的。使用该协议编写的协议,这就是REST的核心思想之一。因此,状态码必须是协议的一部分。
Ariel M.

状态代码的目的是在各种编程语言,框架和方法之间提供一种通用的理解语言。状态代码的含义几乎是通用的:您的自定义主体(通过API使用者必须学习的自定义语法在本质上增加了复杂性)不是。
Kelsey Hannan '18

40

请记住,状态代码比HTTP / 1.1 RFC中定义的状态代码更多,IANA注册中心位于http://www.iana.org/assignments/http-status-codes。对于您提到的情况,状态码507听起来不错。


3
嗯,虽然乍一看“ 507存储空间不足”似乎是合适的,但我不愿意使用它,因为它是作为(相当特定的)WebDAV扩展而不是一般的“嘿,您的空间不足”例外。不过,我想您可以使用它。
最多

1
不,这完全不是特定于WebDAV的。有一个用于HTTP状态代码的注册表的原因。
朱利安·雷施克

25
我不同意507这个目的。我的解释507是服务器空间不足,而不是帐户空间不足。
帕特里克

11
我同意帕特里克。5xx错误是与服务器有关的错误。
肖恩

10
418:“我是茶壶”,意味着存储空间太小(就像茶壶很小)而不是很大,因此空间不足。
Steve Konves 2013年

22

正如其他人指出的那样,在错误代码中包含响应实体是完全允许的。

请记住,5xx错误是服务器端的错误,也就是客户端无法更改其请求以使请求通过。如果超出了客户端的配额,那么这绝对不是服务器错误,因此应避免使用5xx。


我不同意。超出配额将是服务器错误(5xx),因为:客户端的请求有效,并且如果配额不足,则该请求成功,这将排除400系列。
mikek3332002

3
但是服务器没有做错任何事情。
Charlie Schliesser 2014年

20

有两种错误。应用程序错误和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)

但是,如何设计应用程序错误实际上取决于您。堆栈溢出例如发送出与对象responsedatamessage属性。我认为响应包含truefalse指示该操作是否成功(通常用于写操作)。数据包含有效负载(通常用于读取操作),并且消息包含任何其他元数据或有用的消息(例如,response是时的错误消息false)。


1
400还有助于指示客户端应用程序中的问题。
支石墓

19

我知道这对于聚会来说非常晚了,但是现在,在2013年,我们有几种媒体类型可以以常见的分布式(RESTful)方式处理错误处理。请参阅application / vnd.error + json(https://github.com/blongden/vnd.error)中的“ vnd.error”和application / problem + json(https://tools.com)中的“ HTTP API问题详细信息” 。 ietf.org/html/draft-nottingham-http-problem-05)。


2
感谢您的链接。draft-nottingham-http-problem现在是提议的标准:datatracker.ietf.org/doc/rfc7807
seanf

9

同意 REST的基本原理是使用Web基础结构。HTTP状态代码是一种消息传递框架,它允许各方在不增加HTTP有效负载的情况下彼此通信。它们已经建立了传达响应状态的通用代码,因此,要真正实现RESTful,应用程序必须使用此框架来传达响应状态。

在HTTP 200信封中发送错误响应会产生误导,并迫使客户端(api使用者)最有可能以非标准或专有方式来解析消息。这也不是很有效-您将迫使客户端每次都解析HTTP有效负载以了解“真实”响应状态。这增加了处理,增加了延迟,并为客户端提供了一个出错的环境。


3
无论您有成功的响应还是失败的响应,您都很有可能将解析该响应。如果是错误,则要解析它以显示错误消息。错误响应通常很小,并且可以快速解析。我认为我们不应该担心尝试优化以避免解析错误响应。您是否不分析就丢弃错误响应?我认为这是不明智的。
AgilePro

3
如果您获得200 OK,则可以选择不对其进行解析,具体取决于您的业务规则。关键不是我们是否一直在解析它。重点是意图-200 OK的意图是什么?通过发送包装在200 OK中的错误消息,您正在破坏意图。
Kingz

1
“ 200 OK的目的是什么?” -表示传输层成功。该请求已成功收到并得到回答,只是一个与HTTP无关的特定于应用程序的问题。+++把倒过来:在REST世界意味着发送404 的东西没有找到,也许URL是完全错误的或要处理的资源或其他任何东西没有被发现。不解析消息,您将无法解析。恕我直言REST只是合并图层。
maaartinus

合并是常态。它为您提供了适合您的推理路线的语法,使您可以将精力集中在业务层上。同意传输以后的状态通信-最初的目的是-REST不是与HTTP同时发明/提出的-后来出现了,只是决定使用现有的基础结构来表示状态及其更改。
金兹


5

请坚持协议的语义。将2xx用于成功响应,将4xx和5xx用于错误响应-无论是业务异常还是其他情况。如果将2xx用于任何响应是协议中的预期用例,则它们最初将没有其他状态代码。


3

不要忘记5xx错误以及应用程序错误。

在这种情况下,409(冲突)呢?这假定用户可以通过删除存储的资源来解决问题。

否则507(并非完全标准)也可能起作用。除非您通常将200用于错误,否则我不会使用200。


-1

如果超出了客户端配额,则是服务器错误,在这种情况下,请避免使用5xx。


2
当服务器错误时为什么要避免5xx系列错误?
mikek3332002

6
“超出客户端配额”不是服务器错误,而是客户端限制,应低于4xx。
MyGGaN
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.