REST:将应用程序错误映射到HTTP状态码

37

在设计一个基于几个传统应用的 web 服务 API 时,除了 Response Body 中的 JSON/XML 数据结构外,我们还希望返回使 Web 缓存和开发人员都能理解的 HTTP 状态码。但是,如何将不同类型的错误映射到适当的 HTTP 状态码上呢?团队中的每个人都同意以下内容:

GET /package/1234 返回 404 Not Found 如果 1234 不存在

GET /package/1234/next_checkpoint 如果“next_checkpoint” 和 1234 都是有效的但是 next_checkpoint 在此处无意义,则返回 400 Bad Request

以此类推... 但是,在某些情况下,需要更具体的描述而不仅仅是 “400” - 例如:

POST /dispatch/?for_package=1234 如果 /dispatch 和包 1234 都存在,但 1234 还没有准备好进行调度,则返回 412 Precondition Failed

这样做是否被认为是良好实践,即重用 RFC HTTP 状态码,还是我们应该创造新的状态码,这些状态码与我们特定的错误原因完全对应?


(编辑:HTTP/1.1 中的状态码WebDAV 扩展中的状态码

5个回答

24

RESTful使用HTTP意味着您必须保持API的一致性。这意味着您不能添加特定于领域的方法(如GET_STOCK_QUOTE),但也意味着您不能添加特定于领域的错误代码(如499产品缺货)。

事实上,HTTP客户端错误代码是一个很好的设计检查,因为如果您正确设计资源语义,HTTP错误代码的含义将正确地表达任何错误。如果您觉得需要其他错误代码,则您的资源设计可能是错误的。

Jan


问题是:当RFC规定“3位数字后跟空格”时,为什么最常见的Web服务器可以使用所有这些“子状态”代码?http://support.microsoft.com/kb/943891/ - conny
3
请注意,WebDAV不是一个特定的应用程序。它是HTTP统一接口的扩展。重用其中一些扩展(例如422)是有意义的,但有些扩展会破坏REST的约束(如all或PROP*),或者破坏HTTP本身(如COPY、MOVE)。这些扩展不应该被重用。 - Jan Algermissen
1
以 PATCH 为例考虑。那是 HTTP 的一个非常好的扩展。或者有时提到用 HTTP 进行发布订阅的 WATCH(或 MONITOR): <code> WATCH /my/feed Reply-To: http://some.org/please/send/notification/here </code> 简 - Jan Algermissen
PATCH是多余的;它解决了PUT中实际上在RFC 2616中并不存在的一个问题。 - wprl
嗨wprl,PATCH解决的问题实际上不存在吗? - Jan Algermissen
显示剩余4条评论

20

5

GET /package/1234/next_checkpoint 如果“next_checkpoint”和1234是有效的,但在此处不合理,则返回400 Bad Request。

这种方式不正确来考虑URI。

URI是不透明的,因此从客户端的角度观察其部分是否“有效”或其他部分是否“无效”没有任何意义。因此,您应该向客户端“只”返回404,因为资源“package/1234/next_checkpoint”不存在。


4
当客户端出现错误时,您应该使用最符合您请求的4xx系列响应,但要小心不要使用那些针对特定标头或条件的响应。我倾向于返回一个易于理解的状态消息以及响应体中的纯文本版本或结构化错误消息,具体取决于应用程序上下文。
更新:在进一步阅读RFC后,“procondition failed”是针对条件标头(例如“if-none-match”)的。我会给出一个一般的400消息。

关于这个问题,还有一个相关的SO线程:https://dev59.com/a3I-5IYBdhLWcg3wO1rl - Steve Pomeroy
支持这种观点的另一件事是:XCAP规范(RFC4825,使用HTTP)在出现XCAP客户端错误时使用400响应代码。 - Steve Pomeroy
Webdav(rfc2518)也会在请求体有误时使用400响应代码。 - Steve Pomeroy

-1
实际上,你根本不应该这样做。你正确地使用了404 Not Found,但是400 Bad Request被错误地使用了。根据RFC,400 Bad Request仅在HTTP协议格式错误时使用。在你的情况下,请求在语法上是正确的,只是有一个意外的参数。你应该返回一个500 Server Error,然后在你的REST结果中包含一个错误代码。

5
真的吗?它只是说:“由于格式不正确,服务器无法理解请求。客户端不应重复未经修改的请求。” 它没有明确指出错误是在HTTP还是请求的应用层位。对于客户端发送了不正确数据的请求而言,500服务器错误过于笼统。我倾向于将500错误视为不应该发生的事情(如编程错误之类),而4xx系列则表示“无效输入”。 - Steve Pomeroy
20
400系列是指客户端出现错误,500系列是指服务器出现错误。在这些情况下,服务器没有引起错误,因此500无效。 - Darrel Miller
4
RFC所提到的“语法”是指HTTP语法。你正在查看HTTP RFC;它怎么可能在谈论一个低层OSI构造的应用层语法错误?这里适用服务器错误,因为服务器无法继续进行。从应用程序角度来看,客户端可能有错,但从HTTP角度来看,会话无法继续进行是服务器的错误。 - David Pfeffer
3
HTTP是一种应用层协议,其响应代码旨在被分布式应用程序用于指示应用程序错误。 - Darrel Miller
7
RESTful HTTP的主要目的是提供/遵循客户端和服务器交互的统一机制,也就是说,没有什么需要添加或在其上加层。以RESTful方式利用HTTP的应用程序不会在HTTP之上“叠加”任何东西;它们是(故意)受其架构限制和管理的。在RESTful应用程序中,客户端通过通过HTTP(而不是在HTTP之上)交换(超媒体)表现形式来驱动。 - Mike
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接