对于失败的验证或无效的重复项,我应该使用哪个状态代码?
我正在使用基于 REST 的 API 构建一个应用程序,并且已经为每个请求指定状态代码。
对于验证失败的请求或尝试在数据库中添加重复项的请求,我应该发送什么状态代码?
我浏览过 http://www.w3.org/Protocols/rfc2616/ rfc2616-sec10.html 但它们似乎都不正确。
发送状态代码时有常见的做法吗?
I am building an application with a REST-based API and have come to the point where I am specifying status codes for each requests.
What status code should i send for requests failing validation or where a request is trying to add a duplicate in my database?
I've looked through http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html but none of them seems right.
Is there a common practice when sending status codes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
对于输入验证失败: 400 Bad Request + 您的可选描述。 “RESTful Web Services”一书中建议了这一点。
对于双重提交:409 冲突
6 月更新2014
相关规范曾经是RFC2616,其中给出了400的使用(错误的请求)相当狭隘地作为
因此可能有人认为它不适合语义错误。但现在不再是了;自 2014 年 6 月起,相关标准 RFC 7231 取代了之前的 RFC2616,给出了使用400(错误请求) 更广泛地称为
For input validation failure: 400 Bad Request + your optional description. This is suggested in the book "RESTful Web Services".
For double submit: 409 Conflict
Update June 2014
The relevant specification used to be RFC2616, which gave the use of 400 (Bad Request) rather narrowly as
So it might have been argued that it was inappropriate for semantic errors. But not any more; since June 2014 the relevant standard RFC 7231, which supersedes the previous RFC2616, gives the use of 400 (Bad Request) more broadly as
我推荐状态代码 422,“无法处理的实体”。
I recommend status code 422, "Unprocessable Entity".
您绝对应该在响应标头和/或正文中给出更详细的解释(例如,使用自定义标头 -
X-Status-Reason:验证失败
)。You should definitely give a more detailed explanation in the response headers and/or body (e.g. with a custom header -
X-Status-Reason: Validation failed
).200,300,400,500都非常通用。如果你想要通用的,400就可以了。
422 被越来越多的 API 使用,甚至被 Rails 开箱即用。
无论您为 API 选择哪种状态代码,都会有人不同意。但我更喜欢 422,因为我认为“400 + 文本状态”太笼统。此外,您没有利用 JSON-ready 解析器;相比之下,带有 JSON 响应的 422 非常明确,可以传达大量错误信息。
说到 JSON 响应,我倾向于标准化这种情况下的 Rails 错误响应,即:
这种格式非常适合表单验证,我认为就“错误报告丰富性”而言,这是需要支持的最复杂的情况。如果您的错误结构是这样的,它可能会满足您所有的错误报告需求。
200,300, 400, 500 are all very generic. If you want generic, 400 is OK.
422 is used by an increasing number of APIs, and is even used by Rails out of the box.
No matter which status code you pick for your API, someone will disagree. But I prefer 422 because I think of '400 + text status' as too generic. Also, you aren't taking advantage of a JSON-ready parser; in contrast, a 422 with a JSON response is very explicit, and a great deal of error information can be conveyed.
Speaking of JSON response, I tend to standardize on the Rails error response for this case, which is:
This format is perfect for form validation, which I consider the most complex case to support in terms of 'error reporting richness'. If your error structure is this, it will likely handle all your error reporting needs.
数据库中的重复项应为
409 CONFLICT
。我建议使用
422 UNPROCESSABLE ENTITY
来处理验证错误。我在此处提供了 4xx 代码的详细说明。
A duplicate in the database should be a
409 CONFLICT
.I recommend using
422 UNPROCESSABLE ENTITY
for validation errors.I give a longer explanation of 4xx codes here.
200
呃...(309, 400, 403, 409, 415, 422)...很多答案试图猜测、争论和标准化的最佳返回代码HTTP 请求成功,但 REST 调用失败。
混合使用 HTTP 状态代码和 REST 状态代码是错误。
然而,我看到许多实现混合了它们,许多开发人员可能不同意我的观点。
HTTP 返回码与
HTTP 请求
本身相关。 REST 调用是使用超文本传输协议请求完成的,它的工作级别低于调用的 REST 方法本身。 REST 是一种概念/方法,其输出是业务/逻辑结果,而HTTP 结果代码是传输结果。例如,当您调用 /users/ 时返回“404 Not found”会令人困惑,因为它可能意味着:
“403 Forbidden/Access Denied”可能意味着:
并且列表可能会继续显示“500 服务器错误”(Apache/Nginx HTTP 引发的错误或 REST 中的业务约束错误)或其他 HTTP 错误等...
从代码中,很难理解失败原因是什么,是 HTTP(传输)失败还是 REST(逻辑)失败
如果 HTTP 请求在物理上成功执行,则无论记录如何,它都应该始终返回 200 代码。 (s) 是否找到。因为 找到 URI 资源并由 HTTP 服务器处理。是的,它可能会返回一个空集,其中包含 200 作为 HTTP。结果,对吗?
您可以返回 200 HTTP 代码,并带有一些选项:
,一些互联网提供商可能会拦截您的请求并返回 404 HTTP 代码,这并不意味着找不到您的数据,而是在传输级别出现问题。
来自 Wiki:
为什么不简单地回答这样的问题?
Google 总是在其地理编码 API 中返回 200 作为状态代码,即使请求在逻辑上失败:https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
对于成功的 HTTP 请求,Facebook 始终返回 200,即使 REST 请求失败: https://developers.facebook.com/docs/graph -api/using-graph-api/error-handling
很简单,HTTP 状态代码是针对 HTTP 请求的,定义您的状态代码。
200
Ugh... (309, 400, 403, 409, 415, 422)... a lot of answers trying to guess, argue and standardize what is the best return code for a successful HTTP request but a failed REST call.
It is wrong to mix HTTP status codes and REST status codes.
However, I saw many implementations mixing them, and many developers may not agree with me.
HTTP return codes are related to the
HTTP Request
itself. A REST call is done using a Hypertext Transfer Protocol request and it works at a lower level than invoked REST method itself. REST is a concept/approach, and its output is a business/logical result, while HTTP result code is a transport one.For example, returning "404 Not found" when you call /users/ is confuse, because it may mean:
"403 Forbidden/Access Denied" may mean:
And the list may continue with '500 Server error" (an Apache/Nginx HTTP thrown error or a business constraint error in REST) or other HTTP errors etc...
From the code, it's hard to understand what was the failure reason, a HTTP (transport) failure or a REST (logical) failure.
If the HTTP request physically was performed successfully it should always return 200 code, regardless is the record(s) found or not. Because URI resource is found and was handled by the HTTP server. Yes, it may return an empty set. Is it possible to receive an empty web-page with 200 as HTTP result, right?
Instead of this you may return 200 HTTP code with some options:
Also, some internet providers may intercept your requests and return you a 404 HTTP code. This does not means that your data are not found, but it's something wrong at transport level.
From Wiki:
Why not simply answer with something like this?
Google always returns 200 as status code in their Geocoding API, even if the request logically fails: https://developers.google.com/maps/documentation/geocoding/intro#StatusCodes
Facebook always return 200 for successful HTTP requests, even if REST request fails: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling
It's simple, HTTP status codes are for HTTP requests. REST API is Your, define Your status codes.
Ember-Data 的 ActiveRecord 适配器期望从服务器返回
422 UNPROCESSABLE ENTITY
。因此,如果您的客户端是用 Ember.js 编写的,则应该使用 422。只有这样 DS.Errors 才会填充返回的错误。 您当然可以将 422 更改为适配器中的任何其他代码 。Ember-Data's ActiveRecord adapter expects
422 UNPROCESSABLE ENTITY
to be returned from server. So, if you're client is written in Ember.js you should use 422. Only then DS.Errors will be populated with returned errors. You can of course change 422 to any other code in your adapter.状态代码 304 未修改 也会对重复请求做出可接受的响应。这类似于使用实体标签处理
If-None-Match
标头。在我看来,@Piskvor 的答案对于我所认为的原始问题的意图来说是更明显的选择,但我有一个也相关的替代方案。
如果您希望将重复请求视为警告或通知而不是错误,则响应状态代码为
304
Not Modified,并且Content-Location
标头标识现有资源同样有效。当目的只是为了确保资源存在时,重复请求不会是错误,而是确认。请求并没有错误,只是多余,客户端可以参考现有的资源。换句话说,请求是好的,但是由于资源已经存在,所以服务器不需要进行任何进一步的处理。
Status Code 304 Not Modified would also make an acceptable response to a duplicate request. This is similar to processing a header of
If-None-Match
using an entity tag.In my opinion, @Piskvor's answer is the more obvious choice to what I perceive is the intent of the original question, but I have an alternative that is also relevant.
If you want to treat a duplicate request as a warning or notification rather than as an error, a response status code of
304
Not Modified andContent-Location
header identifying the existing resource would be just as valid. When the intent is merely to ensure that a resource exists, a duplicate request would not be an error but a confirmation. The request is not wrong, but is simply redundant, and the client can refer to the existing resource.In other words, the request is good, but since the resource already exists, the server does not need to perform any further processing.
我得出的结论是尝试遵循这个规则:如果它表明客户端开发人员错误,请使用
400
(错误请求)。否则,假设根本没有客户端验证,如果愚蠢用户输入无效数据,则使用422
(不可处理实体)。如果有疑问,请优先选择422
,或者也许使用更容易实现的。这有助于开发人员知道谁真正犯了错误,无论是他自己还是用户。
我所说的“愚蠢的用户”是指非技术用户。攻击者在这里不重要:如果您担心的话,您一开始就不会使用 HTTP 状态代码。 :)
例如,如果您要根据 JSON 架构验证 JSON 请求正文,则
400
是正确的选择(例如缺少键、关键字不匹配)。但是,如果您希望用户输入有效的电子邮件,那么您应该使用422
(让我再说一遍,假设没有客户端验证)。这也有助于更好的分支逻辑。例如,在 REST API 的上下文中,假设您有一个调查响应端点,可能具有 POST 和 PATCH 方法。在这种情况下,如果客户端发送无效的 POST 请求,当状态代码为
422
时,您可能需要将新资源的 URI 发送回Location
标头中,但不适用于400
。现实世界的例子肯定更复杂,但恕我直言,这应该很有效。
I came to the conclusion to try to follow this rule: If it indicates the client developer error, go with
400
(Bad Request). Otherwise, supposing no client validation at all, if a dumb user is entering invalid data, then use422
(Unprocessable Entity). If in doubt, prefer422
, or maybe use the one with easier implementation.This helps the developer to know who actually made the mistake, whether himself or the user.
By a dumb user, I mean non-technical user. An attacker shouldn't matter here: If you were that worried about, you wouldn't use HTTP status codes in the first place. :)
For example, if you're validating a JSON request body against a JSON Schema,
400
is the proper choice (e.g. missing keys, keyword mismatches). However, if you're expecting user to enter a valid email, then you should use422
(let me say again, suppose there is no client validation).This can also be helpful in better branching logics. For instance, in the context of a REST API, suppose you have a survey response endpoint, with possible methods of POST and PATCH. In this case, if a client sends an invalid POST request, you might want to send the URI of the new resource back in the
Location
header for when the status code is422
, but not for400
.Real world examples are more complicated for sure, but this should work great IMHO.
我想每个人对此都会有不同的看法,因为我们都在不同的上下文中提到过状态代码。但重要的是最广泛接受和了解的东西。 400 被认为是验证错误响应并被接受,而 409 顾名思义是冲突。如果我们说 400 不适合验证错误,因为服务器已经理解了请求,那么想象一下有人问你一个你确实从文字中理解的问题,但你可以回答并说“哦,这是一个无效的问题”或“这确实如此”没有意义”,所以仅仅因为你理解了这些词并不意味着它有意义。否则我们可以整天谈论这个
I think everyone will have different opinion on this because we all have referred to status codes in various contexts. But what is important is whatever is most widely accepted and known. 400 is known and accepted as validation error response and 409 as name suggests is a conflict. If we say 400 is not right for validation error because server has understood the request, then think of someone asking you a question which you do understand from words but you could have responded and said "oh that is an invalid question" or "that does not make sense" so just because you understood the words does not mean it makes sense. Otherwise we can keep talking about this all day