400对422对数据POST的响应

问题描述 投票:294回答:9

我正在尝试使用我正在处理的“类似REST”的API来确定在不同场景下返回的正确状态代码。假设我有一个终点允许以JSON格式进行POST'ing购买。它看起来像这样:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

如果客户向我发送“sales_tax”(而不是预期的“税收”),我应该返回什么。目前,我要回400.但是,我已经开始质疑自己了。我应该真的回来422吗?我的意思是,它是JSON(支持)并且它是有效的JSON,它只是不包含所有必需的字段。

rest http-status-codes
9个回答
363
投票

400 Bad Request现在似乎是您的用例的最佳HTTP / 1.1状态代码。

在您的问题(和我的原始答案)时,RFC 7231不是一个东西;在那一点上,我反对400 Bad Request,因为RFC 2616说(强调我的):

由于语法格式错误,服务器无法理解请求。

并且您描述的请求是语法上有效的JSON,它包含在语法上有效的HTTP中,因此服务器对请求的语法没有任何问题。

然而as pointed out by Lee Saferite in the commentsRFC 7231, which obsoletes RFC 2616, does not include that restriction

400(错误请求)状态代码指示服务器由于被认为是客户端错误(例如,格式错误的请求语法,无效请求消息成帧或欺骗性请求路由)而不能或不会处理该请求。


但是,在重新措辞之前(或者如果您想对RFC 7231只是现在提出的标准进行狡辩),422 Unprocessable Entity似乎不是您的用例的错误HTTP状态代码,因为the introduction to RFC 4918 says:

虽然HTTP / 1.1提供的状态代码足以描述WebDAV方法遇到的大多数错误情况,但有些错误并不能完全落入现有类别。该规范定义了为WebDAV方法开发的额外状态代码(第11节)

the description of 422说:

422(不可处理实体)状态代码表示服务器理解请求实体的内容类型(因此415(不支持的媒体类型)状态代码是不合适的),并且请求实体的语法是正确的(因此是400(错误请求) )状态代码不合适)但无法处理包含的指令。

(注意语法的引用;我怀疑7231也部分淘汰了4918)

这听起来与你的情况完全一样,但万一有任何疑问,它继续说:

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

(将“XML”替换为“JSON”,我想我们可以同意这是你的情况)

现在,有些人会反对RFC 4918是关于“Web分布式创作和版本控制的HTTP扩展(WebDAV)”,并且你(大概)没有涉及WebDAV,所以不应该使用它。

鉴于在原始标准中使用明确不包括情况的错误代码与从描述情况的扩展中使用错误代码之间的选择,我会选择后者。

此外,RFC 4918 Section 21.4指的是IANA Hypertext Transfer Protocol (HTTP) Status Code Registry,其中422可以找到。

我建议HTTP客户端或服务器使用该注册表中的任何状态代码是完全合理的,只要它们正确地这样做。


但是从HTTP / 1.1开始,RFC 7231有牵引力,所以只需使用400 Bad Request


32
投票

反映截至2015年的状况:

客户和中介机构对400和422响应代码的行为将被视为相同,因此它实际上并没有使用您具体的差异。

但是我希望看到400目前使用得更广泛,而且HTTPbis spec提供的澄清使它更适合这两个状态代码:

  • HTTPbis规范阐明了400不仅仅是为了语法错误的意图。现在使用更广泛的短语“表示服务器不能或不会因为被认为是客户端错误而处理请求”。
  • 422具体是WebDAV扩展,在RFC 2616或更新的HTTPbis specification中未引用。

对于上下文,HTTPbis是HTTP / 1.1规范的修订版,试图澄清不清楚或不一致的区域。一旦达到批准状态,它将取代RFC2616。


30
投票

400 Bad Request是您的用例的正确HTTP状态代码。代码由HTTP / 0.9-1.1 RFC定义。

由于语法格式错误,服务器无法理解请求。客户端不应该在没有修改的情况下重复请求。

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 Unprocessable Entity由RFC 4918 - WebDav定义。请注意,与400相比略有不同,请参阅下面引用的文字。

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

为了保持统一的接口,您应该仅在XML响应的情况下使用422,并且您还应该支持Webdav扩展定义的所有状态代码,而不仅仅是422。

http://tools.ietf.org/html/rfc4918#page-78

另见Mark Nottingham关于状态代码的帖子:

尝试将应用程序的每个部分“深入”映射到HTTP状态代码是错误的;在大多数情况下,您希望瞄准的粒度级别更粗糙。如有疑问,可以在没有更好的适合性时使用通用状态代码200 OK,400 Bad Request和500 Internal Service Error。

How to Think About HTTP Status Codes


13
投票

没有正确的答案,因为它取决于您的请求的“语法”的定义。最重要的是你:

  1. 一致地使用响应代码
  2. 在响应正文中包含尽可能多的附加信息,以帮助使用您的API的开发人员找出正在发生的事情。=

在每个人都跳到我面前说这里没有正确或错误的答案之前,让我解释一下我是如何得出结论的。

在此特定示例中,OP的问题是关于包含与预期不同的密钥的JSON请求。现在,收到的关键名称非常相似,从自然语言的角度来看,与预期的密钥非常相似,但它严格地说是不同的,因此机器不会(通常)认为它是等价的。

正如我上面所说,决定因素是语法的含义。如果请求是使用内容类型application/json发送的,那么是,请求在语法上是有效的,因为它是有效的JSON语法,但在语义上没有效果,因为它与预期的不匹配。 (假设严格定义了有问题的请求在语义上是否有效)。

另一方面,如果请求是使用更具体的自定义内容类型(如application/vnd.mycorp.mydatatype+json)发送的,或许可以确切地指定预期的字段,那么我会说请求很容易在语法上无效,因此400响应。

在有问题的情况下,由于密钥错误,而不是值,如果存在有效密钥的规范,则存在语法错误。如果没有有效密钥的规范,或者错误带有值,那么这将是语义错误。


10
投票

案例研究:GitHub API

https://developer.github.com/v3/#client-errors

也许从众所周知的API复制是一个明智的想法:

接收请求主体的API调用有三种可能的客户端错误类型:

发送无效的JSON将导致400 Bad Request响应。

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

发送错误类型的JSON值将导致400 Bad Request响应。

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

发送无效字段将导致422 Unprocessable Entity响应。

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}

4
投票

422 Unprocessable Entity Explained更新日期:2017年3月6日

什么是422不可处理的实体?

当请求格式正确时会发生422状态代码,但是,由于语义错误,无法处理它。这种HTTP状态是在RFC 4918中引入的,更具体地说是针对Web分布式创作和版本控制(WebDAV)的HTTP扩展。

关于开发人员是否应该向客户返回400 vs 422错误存在争议(更多关于以下两种状态之间的差异)。但是,在大多数情况下,只有在您支持WebDAV功能时,才会同意仅返回422状态。

可以在下面阅读从RFC 4918中的第11.2节中获取的422状态代码的逐字定义。

422(不可处理实体)状态代码表示服务器理解请求实体的内容类型(因此415(不支持的媒体类型)状态代码是不合适的),并且请求实体的语法是正确的(因此是400(错误请求) )状态代码不合适)但无法处理包含的指令。

定义继续说:

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

400 vs 422状态代码

错误的请求错误会使用400状态代码,如果请求语法格式错误,包含无效的请求消息框架或具有欺骗性请求路由,则应将错误请求错误返回给客户端。此状态代码可能看起来与422不可处理的实体状态非常相似,但是,区分它们的一小部分信息是422错误的请求实体的语法是正确的,而生成400的请求的语法是正确的。错误不正确。

应仅为非常特殊的用例保留422状态的使用。在由于语法格式错误而发生客户端错误的大多数其他情况下,应使用400 Bad Request状态。

https://www.keycdn.com/support/422-unprocessable-entity/


2
投票

首先,这是一个非常好的问题。

400 Bad Request - When a critical piece of information is missing from the request

例如授权标头或内容类型标头。这是服务器理解请求的绝对必需条件。这可能因服务器而异。

422 Unprocessable Entity - When the request body can't be parsed.

这不如400严重。请求已到达服务器。服务器已经确认请求已经具有正确的基本结构。但无法解析或理解请求正文中的信息。

例如Content-Type: application/xml请求正文是JSON。

这是一篇列出状态代码及其在REST API中的使用的文章。 https://metamug.com/article/status-codes-for-rest-api.php


1
投票

您的情况:从REST角度来看,HTTP 400是您的案例的正确状态代码,因为它在语法上不正确而不是sales_tax而不是tax,尽管它是一个有效的JSON。在将JSON映射到对象时,通常由大多数服务器端框架强制执行。但是,有一些REST实现忽略了JSON对象中的新key。在这种情况下,服务器端可以强制执行仅接受有效字段的自定义content-type规范。

422的理想场景:

在理想的世界中,如果服务器理解请求实体的内容类型并且请求实体的语法正确但由于其语义错误而无法处理数据,则优选422并且通常可接受作为响应发送。

超过422的情况:

请记住,响应代码422是扩展的HTTP(WebDAV)状态代码。仍然有一些HTTP客户端/前端库不准备处理422.对于它们来说,它就像“HTTP 422错误,因为它不是HTTP”一样简单。从服务的角度来看,400并不十分具体。

在企业架构中,服务主要部署在SOA,IDM等服务层上。它们通常服务于从非常旧的本机客户端到最新的HTTP客户端的多个客户端。如果其中一个客户端不处理HTTP 422,则选项是要求客户端升级或将响应代码更改为每个人的HTTP 400。根据我的经验,这些日子非常罕见,但仍有可能。因此,在决定HTTP响应代码之前,始终需要仔细研究您的体系结构。

为了处理这些情况,服务层通常使用versioning或setup configuration flag来发送400严格的HTTP一致性客户端,并为其余的发送422。这样,它们为现有消费者提供向后兼容性支持,但同时为新客户端提供使用HTTP 422的能力。


RFC7321的最新更新说:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

这确认了服务器可以发送HTTP 400以获取无效请求。 400不再仅涉及语法错误,但是,如果客户端可以处理它,422仍然是真正的响应。


-7
投票

您应该实际返回“200 OK”并在响应正文中包含有关发布数据发生的情况的消息。然后由您的应用程序来理解该消息。

问题是,HTTP状态代码正是 - HTTP状态代码。这些意味着仅在传输层有意义,而不是在应用层。应用程序层应该甚至不知道正在使用HTTP。如果您将传输层从HTTP切换到Homing Pigeons,它不应以任何方式影响您的应用层。

让我给你一个非虚拟的例子。让我们说你爱上了一个女孩,她爱你,但她的家人搬到了一个完全不同的国家。她给你她新的蜗牛邮件地址。当然,你决定给她发一封情书。所以你写了你的信,把它放在一个信封里,在信封上写下她的地址,在上面盖章并发送。现在让我们考虑一下这些情况

  1. 你忘了写一个街道名字。您将收到一封未打开的回信,上面写着一条信息,说明该地址格式错误。你搞砸了请求,接收邮局无法处理。这相当于接收“400 Bad Request”。
  2. 所以你修复地址并再次发送信件。但是由于运气不好,你总是拼错了街道的名字。您将再次收到回信,并附上一条消息,说明该地址不存在。这相当于接收“404 Not Found”。
  3. 您再次修复了该地址,这次您设法正确写入地址。你的女孩收到了这封信并给你回信。这相当于接收“200 OK”。然而,这并不意味着你会喜欢她在信中所写的内容。这只是意味着她收到了您的消息,并为您做出回应。在你打开信封并阅读她的信之前,你不知道她是否非常想念你,或者想和你分手。

简而言之:返回“200 OK”并不意味着服务器应用程序对您有好消息。这只意味着它有一些新闻。

PS:422状态代码仅在WebDAV的上下文中有意义。如果您不使用WebDAV,则422具有与任何其他非标准代码完全相同的标准含义=无。

© www.soinside.com 2019 - 2024. All rights reserved.