我正在尝试用我正在开发的“类rest”API找出在不同场景中返回的正确状态代码。假设我有一个端点,允许以JSON格式POST'ing购买。它是这样的:
{
"account_number": 45645511,
"upc": "00490000486",
"price": 1.00,
"tax": 0.08
}
如果客户端发送给我“sales_tax”(而不是预期的“tax”),我应该返回什么?目前,我要返回400分。但是,我开始质疑自己。我真的应该退回422吗?我的意思是,它是JSON(这是受支持的),它是有效的JSON,它只是不包含所有必需的字段。
400 Bad Request是用例的HTTP状态代码。该代码由HTTP/0.9-1.1 RFC定义。
由于格式错误,服务器无法理解请求
语法。客户端不应该重复请求
修改。
https://www.rfc-editor.org/rfc/rfc2616#section-10.4.1
422不可处理实体由RFC 4918 - WebDav定义。请注意,与400相比有轻微的差异,见下面引用的文本。
如果XML
请求主体包含格式良好的(即语法正确),但是
语义错误的XML指令。
为了保持统一的接口,你应该只在XML响应的情况下使用422,你还应该支持Webdav扩展定义的所有状态码,而不仅仅是422。
https://www.rfc-editor.org/rfc/rfc4918#page-78
另见Mark Nottingham关于状态代码的帖子:
试图“深入”映射应用程序的每个部分是错误的。
转换成HTTP状态码;在大多数情况下,粒度级别你
想要的目标要粗糙得多。有疑问时,可以使用
通用状态代码200 OK, 400 Bad Request和500 Internal
没有更好的匹配时的服务错误。
如何看待HTTP状态码
案例研究:GitHub API
https://docs.github.com/en/rest/overview/resources-in-the-rest-api#client-errors
也许从著名的api复制是一个明智的想法:
There are three possible types of client errors on API calls that receive request bodies:
Sending invalid JSON will result in a 400 Bad Request response:
HTTP/1.1 400 Bad Request
Content-Length: 35
{"message":"Problems parsing JSON"}
Sending the wrong type of JSON values will result in a 400 Bad Request response:
HTTP/1.1 400 Bad Request
Content-Length: 40
{"message":"Body should be a JSON object"}
Sending invalid fields will result in a 422 Unprocessable Entity response:
HTTP/1.1 422 Unprocessable Entity
Content-Length: 149
{
"message": "Validation Failed",
"errors": [
{
"resource": "Issue",
"field": "title",
"code": "missing_field"
}
]
}
您的案例:从REST的角度来看,HTTP 400是您案例的正确状态代码,因为发送sales_tax而不是tax在语法上是不正确的,尽管它是一个有效的JSON。在将JSON映射到对象时,大多数服务器端框架通常会强制执行这一点。然而,有一些REST实现忽略JSON对象中的new键。在这种情况下,服务器端可以强制使用只接受有效字段的自定义内容类型规范。
422的理想场景:
在理想情况下,如果服务器理解请求实体的内容类型,并且请求实体的语法正确,但由于语义错误而无法处理数据,则首选422,并且通常可以接受将其作为响应发送。
400 / 422的情况:
记住,响应代码422是一个扩展的HTTP (WebDAV)状态码。仍然有一些HTTP客户端/前端库还没有准备好处理422。对他们来说,这就像“HTTP 422是错误的,因为它不是HTTP”一样简单。从服务的角度来看,400并不十分具体。
In enterprise architecture, the services are deployed mostly on service layers like SOA, IDM, etc. They typically serve multiple clients ranging from a very old native client to a latest HTTP clients. If one of the clients doesn't handle HTTP 422, the options are that asking the client to upgrade or change your response code to HTTP 400 for everyone. In my experience, this is very rare these days but still a possibility. So, a careful study of your architecture is always required before deciding on the HTTP response codes.
为了处理类似的情况,服务层通常使用版本控制或设置配置标志对严格符合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仍然是一个真正的响应,前提是客户端可以处理它。