我正在尝试用我正在开发的“类rest”API找出在不同场景中返回的正确状态代码。假设我有一个端点,允许以JSON格式POST'ing购买。它是这样的:

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

如果客户端发送给我“sales_tax”(而不是预期的“tax”),我应该返回什么?目前,我要返回400分。但是,我开始质疑自己。我真的应该退回422吗?我的意思是,它是JSON(这是受支持的),它是有效的JSON,它只是不包含所有必需的字段。


当前回答

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

一致地使用响应代码 在响应体中包含尽可能多的额外信息,以帮助使用API的开发人员弄清楚发生了什么

在大家因为我说这个问题没有正确或错误的答案而责怪我之前,让我解释一下我是如何得出这个结论的。

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

如上所述,决定因素是语法的含义。如果请求是以application/json的内容类型发送的,那么是的,请求在语法上是有效的,因为它是有效的json语法,但在语义上是无效的,因为它不匹配预期的内容。(假设有一个严格的定义,什么使问题中的请求在语义上有效或无效)。

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

在这个问题中,由于键是错误的,而不是值,因此如果存在有效键是什么的规范,就会出现语法错误。如果没有有效键的规范,或者错误是带有值的,那么它将是语义错误。

其他回答

为反映截至2015年的状况:

从行为上讲,客户端和中介端对400和422响应代码的处理是一样的,因此使用哪一种响应代码并没有什么具体的区别。

然而,我希望看到400目前被更广泛地使用,而且HTTPbis规范提供的说明使它成为两种状态代码中更合适的一个:

HTTPbis规范明确了400的意图,不只是用于语法错误。现在使用了更广泛的短语“表示服务器不能或不愿处理由于客户机错误造成的请求”。 422是一个特定的WebDAV扩展,在RFC 2616或更新的HTTPbis规范中没有引用。

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

案例研究: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坏请求-当请求中缺少关键信息时

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

422不可处理实体-当请求体不能被解析时。

这比400要轻。请求已经到达服务器。服务器已经确认请求的基本结构是正确的。但是无法解析或理解请求主体中的信息。

当请求体是JSON时,Content-Type: application/xml。

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

400 -请求验证失败,比如数据丢失,类型错误等等,所以它的状态是400。

422 -通过请求验证,但操作过程失败,因为请求数据,或它的一部分给操作一个错误,但被处理,并给出一个状态422。

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状态码