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

时间:2012-02-21 16:46:53

标签: http rest http-status-codes

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

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

  1. 客户端POSTS订购服务器以获取用户资源。如果用户不存在,则返回404 Not Found。
  2. 验证订单格式和信息。如果无效,则返回400 Bad Request。
  3. 处理订单。如果订单成功,则会为订单返回201 Created。如果遇到意外错误,则返回500服务器错误。
  4. 最后一步是问题 - 如果订单因任何其他原因未完成,我该如何退货?可能的情况包括:

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

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

    编辑:还找到了相同主题的this existing discussion。所有答案似乎都指向使用此类违规的状态代码,并在使用400,409或422扩展名之间进行了一些讨论。

7 个答案:

答案 0 :(得分:77)

您应该使用400作为业务规则。如果订单未被接受,请勿返回2xx。 HTTP是一种应用程序协议,永远不会忘记。如果您返回2xx,则无论您在正文中发送任何信息,客户都可以认为订单已被接受。

<小时/> 来自RESTful Web Services Cookbook

  

某些Web服务的一个常见错误是返回状态   反映成功的代码(状态代码从200到206和300   到307)但包括描述错误条件的消息体。   这样做可以防止HTTP感知软件检测到错误。对于   例如,缓存会将其存储为成功响应并将其提供给   即使客户可能取得成功,后续客户也是如此   请求。

我会留给你在4xx和5xx之间做出决定,但你应该使用错误状态代码。

答案 1 :(得分:20)

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

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

达到的用户最大订单限制也是服务器错误。客户端无法解决该错误。

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

答案 2 :(得分:18)

错误类型:

var words = db.Words
            .Where(W => W.WordForms.Count == 0)
            .ToList();

错误代码:

4×× Client Error

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

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

https://httpstatuses.com/422

答案 3 :(得分:9)

我知道这个问题已经过时了,但我今天想出了同样的问题。如果我的用户没有信用,我的REST API应该返回什么状态代码?

我倾向于倾向402 Payment Required

根据Wikipedia

  

保留供将来使用。最初的意图是这些代码可能被用作某种形式的数字现金或微支付方案的一部分,但这种情况并未发生,并且通常不使用此代码。如果特定开发者已超过请求的每日限制,则Google Developers API会使用此状态。

确实是they do

  

PAYMENT_REQUIRED(402)

     
      
  • 已达到开发者设定的每日预算限额。
  •   
  • 请求的操作需要的资源多于配额允许的资源。需要付款才能完成操作。
  •   
  • 请求的操作需要经过身份验证的用户进行某种付款。
  •   

答案 4 :(得分:2)

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

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

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

我建议我们应该在这些场景中使用403并附带相应的错误消息。

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

答案 5 :(得分:2)

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

  

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

但是还有this definition

  

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

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

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


另一个选项可能是422 Unprocessable Entity

  

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

     

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

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


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

表示
  

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

     

服务器可以发送Retry-After标头字段,以建议客户端在重试请求之前要等待的适当时间。

答案 6 :(得分: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