我正在尝试使用我正在处理的“类似REST”的API来确定在不同场景下返回的正确状态代码。假设我有一个终点允许以JSON格式进行POST'ing购买。它看起来像这样:
{
"account_number": 45645511,
"upc": "00490000486",
"price": 1.00,
"tax": 0.08
}
如果客户向我发送“sales_tax”(而不是预期的“税收”),我应该返回什么。目前,我要回400.但是,我已经开始质疑自己了。我应该真的回来422吗?我的意思是,它是JSON(支持)并且它是有效的JSON,它只是不包含所有必需的字段。
答案 0 :(得分:357)
400 Bad Request 现在似乎是您用例的最佳HTTP / 1.1状态代码。
在您提问时(以及我的原始答案),RFC 7231不是一件事;在那一点上,我反对400 Bad Request
,因为RFC 2616说(强调我的):
由于语法格式错误,服务器无法理解该请求。
并且您描述的请求是语法上有效的JSON,它包含在语法上有效的HTTP中,因此服务器对请求的语法没有任何问题。
然而 as pointed out by Lee Saferite in the comments,RFC 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节)
422(不可处理实体)状态代码表示服务器 了解请求实体的内容类型(因此a 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
!
答案 1 :(得分:32)
反映截至2015年的状态:
客户和中介机构对400和422响应代码的处理方式相同,因此它实际上并没有与您使用的具体区别。
但是,我希望看到400目前使用得更广泛,而HTTPbis spec提供的说明使其更适合两种状态代码:
对于上下文,HTTPbis是HTTP / 1.1规范的修订版,试图澄清不清楚或不一致的区域。一旦达到批准状态,它将取代RFC2616。
答案 2 :(得分:29)
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 没有更好的适合度时服务错误。
答案 3 :(得分:13)
没有正确的答案,因为它取决于您的请求的“语法”的定义。最重要的是你:
在每个人都跳到我面前说这里没有正确或错误的答案之前,让我解释一下我是如何得出结论的。
在此特定示例中,OP的问题是关于包含与预期不同的密钥的JSON请求。现在,收到的关键名称非常相似,从自然语言的角度来看,与预期的密钥非常相似,但它严格地说是不同的,因此不会(通常)被机器识别为等效的。
正如我上面所说,决定因素是语法的含义。如果请求的内容类型为application/json
,那么请求语法有效,因为它是有效的JSON语法,但语义无效,因为它与预期的不符。 (假设严格定义了有问题的请求在语义上是否有效)。
另一方面,如果请求是使用更具体的自定义内容类型(如application/vnd.mycorp.mydatatype+json
)发送的,或许可以准确指定预期的字段,那么我会说请求很容易在语法上无效因此400响应。
在相关案例中,由于键错误,而不是值,因此存在语法错误是有效密钥的规范。 如果有效密钥没有规范,或者错误的值为,那么它将是语义错误。
答案 4 :(得分:9)
案例研究:GitHub API
https://developer.github.com/v3/#client-errors
也许从知名的API复制是一个明智的主意:
接收请求正文的API调用上可能存在三种类型的客户端错误:
发送无效的JSON将导致400错误的请求响应。
HTTP/1.1 400 Bad Request Content-Length: 35 {"message":"Problems parsing JSON"}
发送错误类型的JSON值将导致400错误的请求响应。
HTTP/1.1 400 Bad Request Content-Length: 40 {"message":"Body should be a JSON object"}
发送无效字段将导致422无法处理的实体响应。
HTTP/1.1 422 Unprocessable Entity Content-Length: 149 { "message": "Validation Failed", "errors": [ { "resource": "Issue", "field": "title", "code": "missing_field" } ] }
答案 5 :(得分:4)
422 Unprocessable Entity Explained更新时间:2017年3月6日
422无法处理的实体是什么?
当请求格式正确时,会发生422状态代码 语义错误无法处理。此HTTP状态为 在RFC 4918中引入,更具体地说是针对HTTP Web分布式创作和版本控制(WebDAV)的扩展。
关于开发人员是否存在争议 应该向客户返回400 vs 422错误(更多关于差异 在以下两种状态之间)。但是,在大多数情况下,都同意了 只有在你支持WebDAV时才能返回422状态 能力。
从部分获取的422状态代码的逐字定义 RFC 4918中的11.2可以在下面阅读。
422(不可处理实体)状态代码表示服务器 了解请求实体的内容类型(因此a 415(不支持的媒体类型)状态代码不合适),和 请求实体的语法是正确的(因此是400(错误请求) 状态代码不合适但是无法处理包含的内容 指令。
定义继续说:
例如,如果是XML请求正文,则可能会出现此错误情况 包含格式良好(即语法正确),但语义上 错误的XML指令。
400 vs 422状态代码
错误的请求错误会使用400状态代码,应该是 如果请求语法格式错误,则返回到客户端,包含 无效的请求消息框架,或具有欺骗性请求路由。 此状态代码可能看起来非常类似于422无法处理 然而,实体状态是一小部分信息 它们的区别在于请求实体的语法 422错误是正确的,而生成的请求的语法 400错误不正确。
422状态的使用应仅保留用于非常特殊 用例。在发生客户端错误的大多数其他情况下 如果语法错误,则应使用400 Bad Request状态。
答案 6 :(得分:2)
首先,这是一个非常好的问题。
e.g。授权标头或内容类型标头。这是服务器理解请求的绝对必需条件。这可能因服务器而异。
这不如400严重。请求已到达服务器。服务器已经确认请求已经具有正确的基本结构。但是,请求体中的信息无法被解析或理解。
e.g。请求正文为JSON时Content-Type: application/xml
。
这是一篇列出状态代码及其在REST API中的使用的文章。 https://metamug.com/article/status-codes-for-rest-api.php
答案 7 :(得分:1)
您的案例 HTTP 400
是您的案例的正确状态代码,从REST角度来看,因为它在语法上不正确而不是sales_tax
而不是tax
,一个有效的JSON。在将JSON映射到对象时,通常由大多数服务器端框架强制执行。但是,有些REST实现会忽略JSON对象中的新key
。在这种情况下,服务器端可以强制执行仅接受有效字段的自定义content-type
规范。
422的理想情景:
在理想的世界中, 422 是首选的,如果服务器了解请求实体的内容类型且请求实体的语法正确但无法处理,则通常可接受作为响应发送数据因为它在语义上是错误的。
400超过422的情况:
请记住,响应代码422是扩展HTTP(WebDAV)状态代码。还有一些HTTP客户端/前端库不准备处理422.对于它们来说,它就像“HTTP 422一样简单,因为它不是HTTP”。从服务的角度来看,400并不是特定的。
在企业架构中,服务主要部署在SOA,IDM等服务层上。它们通常服务于从非常旧的本机客户端到最新的HTTP客户端的多个客户端。如果其中一个客户端不处理HTTP 422,则选项是要求客户端升级或将响应代码更改为每个人的HTTP 400。根据我的经验,这些日子非常罕见,但仍有可能。因此,在决定HTTP响应代码之前,始终需要仔细研究您的体系结构。
为了处理这些情况,服务层通常使用versioning
或设置configuration
标志,以便严格的HTTP一致性客户端发送400,并为其余的发送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仍然是真正的响应。
答案 8 :(得分:-7)
您应该实际返回“200 OK”,并在响应正文中包含有关发布数据发生的情况的消息。然后由您的应用程序来理解该消息。
问题是,HTTP状态代码正是 - HTTP状态代码。这些意味着仅在传输层有意义,而不是在应用层。应用程序层应该甚至不知道正在使用HTTP。如果您将传输层从HTTP切换到Homing Pigeons,它不会以任何方式影响您的应用层。
让我举一个非虚拟的例子。让我们说你爱上了一个女孩,她爱你,但她的家人搬到了一个完全不同的国家。她给你她新的蜗牛邮件地址。当然,你决定给她发一封情书。所以你写了你的信,把它放在一个信封里,在信封上写下她的地址,在上面盖章并发送。现在让我们考虑一下这些场景
简而言之:返回“200 OK”并不意味着服务器应用程序对您有好消息。这只意味着它有一些新闻。
PS:422状态代码仅在WebDAV的上下文中有意义。如果您不使用WebDAV,则422具有与任何其他非标准代码完全相同的标准含义=无。