对于一般的不成功请求(不是错误),适当的HTTP状态代码响应是什么?


109

我正在创建一个RESTful API,它将处理许多用户交互,包括使用存储的信用卡下订单。

如果订单成功,我将返回200 OK,如果订单请求格式错误或无效,我将返回400 Bad Request。但是,如果订单的实际处理过程中出现问题,我应该退货吗?

  1. 客户端向服务器发送POSTS命令以获取用户资源。如果用户不存在,则返回404 Not Found。
  2. 订单格式和信息已验证。如果无效,则返回400 Bad Request。
  3. 订单已处理。如果订单成功,则为订单返回201 Created。如果遇到意外错误,则返回500服务器错误。

最后一步是问题-如果由于其他原因导致订单未完成,我该怎么办?可能的情况包括:

  • 产品售罄
  • 达到用户最大订单数限制
  • 信用卡交易失败(资金不足等)

这似乎不适合400或500。如果没有更好的代码,如果我能将其视为400,则根据业务规则,该请求无效。它似乎并不准确。

编辑:还发现了同一主题的现有讨论。那里的所有答案似乎都指向针对这种类型的违规使用状态码,并在使用400、409或422扩展名之间进行了一些讨论。


8
我喜欢“ 422无法处理的实体”来验证错误。并将其用于您的上述示例,并在响应中包含一条实际业务问题“产品已售罄”的消息,如果客户需要根据响应以编程方式做出不同的决定,则可以添加自己的“代码”
house9

在跳入422之前,请考虑是否支持WebDAV功能
Mbithy Mbithy

Answers:


90

您应该将400用于业务规则。如果不接受订单,请不要返回2xx。HTTP是一种应用程序协议,请不要忘记这一点。如果您返回2xx,则无论您在正文中发送的任何信息如何,客户都可以假定订单已被接受。


RESTful Web服务食谱中

一些Web服务犯的一个常见错误是返回一个反映成功的状态代码(状态代码从200到206,从300到307),但包括描述错误情况的消息正文。这样做可以防止支持HTTP的软件检测错误。例如,即使客户端可能能够发出成功的请求,缓存也将其存储为成功的响应并将其提供给后续的客户端。

我将由您决定在4xx和5xx之间进行选择,但是您应该使用错误状态代码。


1
与其他方法相比,您是否有任何示例或参考?您和Widor的答案都是有意义的,一个是从HTTP作为应用程序协议的角度来看,另一个是因为它严格用于传输目的。规范将其定义为“应用程序级协议”,这有点含糊。在研究此内容时,我还在网络上看到了观点和示例。
Raelshark

这是真的。
Young Hyun Yoo

2
您的意思是,“您应该将4xx用于业务规则”?
Yawar

28

如果客户端可以修改请求以解决该错误,则应将4xx用于客户端错误。使用5xx来解决客户端无法真正解决的服务器错误。

产品售罄将是服务器错误。客户端无法以某种方式修改请求以解决错误。您可以切换到其他产品,但这不是一个新请求吗?

达到用户最大订单限制也是服务器错误。客户无法采取任何措施来解决该错误。

信用卡交易失败将是客户错误。客户可以使用其他付款方式或信用卡号重新提交请求,以解决错误。


6
如果达到了订购数量限制,客户是否应该提醒用户注意并允许他们适当地更改其请求?那似乎是一个4xx错误。售罄的产品也是如此。5xx错误旨在用于由系统以某种方式导致故障的错误,而不是用于业务规则不允许的操作。
carlin.scott 2015年

7
我同意以上评论。当服务器出现问题时,将出现5xx错误。业务规则出现4xx错误。
Merc

21

错误类型:

4×× Client Error

错误代码:

422 Unprocessable Entity

服务器了解请求实体的内容类型(因此415不支持的媒体类型状态代码不合适),并且请求实体的语法正确(因此400 Bad Request状态代码不合适),但无法处理包含的内容。说明。

例如,如果XML请求主体包含格式正确(即,语法正确)但语义上错误的XML指令,则可能发生此错误情况。

https://httpstatuses.com/422


16

我知道这个问题很旧,但是今天我想到了同样的问题。如果我的用户用尽了积分,我的REST API应该返回什么状态码?

我倾向于402 Payment Required

根据维基百科

保留以备将来使用。最初的意图是将该代码用作某种形式的数字现金或小额支付方案的一部分,但这种情况并未发生,并且通常不使用。如果特定开发人员超出了请求的每日限制,则Google Developers API将使用此状态。

实际上,他们这样做

PAYMENT_REQUIRED(402)

  • 已达到开发商设定的每日预算限额。
  • 所请求的操作需要的资源超出配额允许的数量。需要付款才能完成操作。
  • 请求的操作需要经过身份验证的用户付款。

这是最深思熟虑和合乎逻辑的答案。
GTodorov

5

怎么424 Failed Dependency样 规范将其描述为:

无法对资源执行该方法,因为请求的操作依赖于另一个操作,并且该操作失败。

但是也有这个定义

状态代码424是在WebDAV标准中定义的,用于客户端需要更改其正在执行的操作的情况-服务器在此没有任何问题。

您可以告诉客户(或假装)您应该执行内部操作以创建订单并扣除余额,并且这些操作之一失败了(尽管出于完全正当的理由),这就是请求失败的原因。

据我所知,“动作”是一个广义的术语,可用于多种情况,包括库存不足,信用不足或仓储派对之夜。


另一种选择可能是422 Unprocessable Entity

服务器了解请求实体的内容类型(因此415不支持的媒体类型状态代码不合适),并且请求实体的语法正确(因此400 Bad Request状态代码不合适),但无法处理包含的内容。说明。

例如,如果XML请求主体包含格式正确(即,语法正确)但语义上错误的XML指令,则可能发生此错误情况。

在语义级别上,尝试请求缺货的商品或信用额不足的商品可能会被视为错误。

MozDev 表示这表明客户端有一个错误,特别是:客户端在未经修改的情况下不应重复此请求。

输入验证失败时,回送4 使用 422。


可以说,库存不足或仓库聚会之夜不足可以被视为临时状态,因此可以稍后再次尝试该请求。这种情况可以表示为503 Service Unavailable

由于暂时的过载或计划的维护,服务器当前无法处理该请求,这可能会在某些延迟后得到缓解。

服务器可以发送一个Retry-After头域来建议一个适当的时间,以便客户端在重试请求之前等待。


这些都与付款无关。我要使用上一个答案中的402!
GTodorov

2

我认为400不能用于所有业务场景。它可用于基本数据输入验证。除此之外,我们可能很难及时将其他业务逻辑放入此错误代码中。这样处理的错误主要是开发人员在客户端编码期间可能遇到的设计时错误。

假设所有参数都是正确的,并且我们正在将用户帐号传递到请求中。

因此,请求现在不再是错误的请求,服务器能够接受该请求。但是现在它拒绝根据新的可用信息完成请求,即-帐户没有足够的余额。

我建议在这些情况下,我们应该将403与相应的错误消息一起使用。

其他可能的错误代码可能是409冲突。但这用于资源处于一致状态的方案中。


-1

我选择406 Not Acceptable

这是一个4xx列表:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585

8
虽然状态码406的名称本身听起来可能准确无误,但您需要知道每个状态码都有权威的文字描述。状态代码406的描述不适用于当前情况。例如,请参阅httpstatuses.com/406
Zero3'1

1
@ Zero3是正确的,此代码表示响应类型不可接受,因为从客户端发送的“接受标头”与端点发送的MediaType之间不匹配,例如application / json与text / plain
Gregor
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.