我正在尝试用我正在开发的“类rest”API找出在不同场景中返回的正确状态代码。假设我有一个端点,允许以JSON格式POST'ing购买。它是这样的:
{
"account_number": 45645511,
"upc": "00490000486",
"price": 1.00,
"tax": 0.08
}
如果客户端发送给我“sales_tax”(而不是预期的“tax”),我应该返回什么?目前,我要返回400分。但是,我开始质疑自己。我真的应该退回422吗?我的意思是,它是JSON(这是受支持的),它是有效的JSON,它只是不包含所有必需的字段。
案例研究: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"
}
]
}
没有正确的答案,因为这取决于对请求的“语法”的定义。最重要的是你:
一致地使用响应代码
在响应体中包含尽可能多的额外信息,以帮助使用API的开发人员弄清楚发生了什么
在大家因为我说这个问题没有正确或错误的答案而责怪我之前,让我解释一下我是如何得出这个结论的。
在这个特定的例子中,OP的问题是关于一个包含不同于预期键的JSON请求。现在,从自然语言的角度来看,接收到的键名与预期的键名非常相似,但严格来说,它是不同的,因此(通常)机器不会认为它们是等效的。
如上所述,决定因素是语法的含义。如果请求是以application/json的内容类型发送的,那么是的,请求在语法上是有效的,因为它是有效的json语法,但在语义上是无效的,因为它不匹配预期的内容。(假设有一个严格的定义,什么使问题中的请求在语义上有效或无效)。
另一方面,如果请求是以更特定的自定义内容类型(如application/vnd.mycorp)发送的。mydatatype+json,也许,确切地指定了期望的字段,那么我会说请求很容易在语法上无效,因此响应为400。
在这个问题中,由于键是错误的,而不是值,因此如果存在有效键是什么的规范,就会出现语法错误。如果没有有效键的规范,或者错误是带有值的,那么它将是语义错误。
案例研究: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"
}
]
}
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状态码