ChatGPT解决这个技术问题 Extra ChatGPT

对于失败的验证或无效的重复,我应该使用哪个状态代码?

我正在使用基于 REST 的 API 构建应用程序,并且已经到了为每个请求指定状态代码的地步。

对于未通过验证的请求或请求尝试在我的数据库中添加副本的位置,我应该发送什么状态代码?

我已经查看了 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html,但似乎没有一个是正确的。

发送状态码时是否有常见的做法?


C
Community

对于输入验证失败:400 Bad Request + 您的可选描述。这在“RESTful Web Services”一书中提出了建议。对于双重提交:409 Conflict

2014 年 6 月更新

相关规范曾经是 RFC2616,它使用 400(Bad Request)相当狭窄

由于语法错误,服务器无法理解该请求

因此,可能有人认为它不适合语义错误。但不再是了;自 2014 年 6 月起,取代之前的 RFC2616 的相关标准 RFC 7231 更广泛地将 400 (Bad Request) 用作

由于被认为是客户端错误,服务器无法或不会处理请求


是的,请求正文是语法的一部分。
错误请求绝对是对此类问题的最常见响应。唯一的其他选择是 422 Unprocessable Entity。它实际上来自 WebDav,但重复使用已在 IANA 注册的任何状态代码是完全有效的。
那么如何区分服务器甚至无法解析的畸形数据和验证错误呢?客户端将完全不同地处理这两个响应。为了验证,他们可能会向用户显示错误。对于真正的“格式错误的数据”,他们会记录错误,以便可以修复生成请求的方法中的错误。
我不同意您对 RFC7231 的解释,尽管它声明 something perceived to be a client error,但本段中给出的所有示例都违反了 HTTP 协议,而不是逻辑错误:语法、帧、路由。因此,我认为 HTTP 规范不允许在应用程序级别上允许 400 验证失败。
为什么不使用 422 - Unprocessable entity?对我来说似乎更合乎逻辑
K
Kyle Macey

验证失败:403 Forbidden(“服务器理解请求,但拒绝执行”)。与流行的观点相反,RFC2616 并没有说“403 仅用于失败的身份验证”,而是“403:我知道你想要什么,但我不会那样做”。这种情况可能是也可能不是由于身份验证。

尝试添加重复:409 Conflict(“由于与资源的当前状态冲突,请求无法完成。”)

您绝对应该在响应标头和/或正文中给出更详细的解释(例如,使用自定义标头 - X-Status-Reason: Validation failed)。


@deamon:那是不是规范,那是维基百科,即某人对“HTTP 状态代码的含义”的看法;请注意,该页面本质上说“这是 Apache 对 403 的含义,这是 IIS 对 403 的含义”,并且它没有引用官方 RFC。您似乎在重复“403 意味着 Apache 所说的任何内容”。不是。实际的 RFC(这是相关文档,不是 Apache 的实现,不是 IIS 的实现,不是其他任何人的实现)在这里:w3.org/Protocols/rfc2616/rfc2616-sec10.html
“10.4.4 403 Forbidden 服务器理解请求,但拒绝执行。授权无济于事,请求不应重复。如果请求方法不是 HEAD 并且服务器希望公开为什么请求没有已完成,它应该描述实体中拒绝的原因。如果服务器不希望将此信息提供给客户端,则可以使用状态码 404(未找到)来代替。我看那里没有重点(“应该/不应该”是 RFC 2119 关键字,不是重点);这就是您的想法,“禁止”是什么意思,而不是 RFC。
我喜欢这个答案,但仍然看到一个小问题。根据 the spec,当返回 403 时,“不应重复请求”。但是,返回 409 “仅在预期用户可能能够解决冲突并重新提交请求的情况下才允许”。在重复的情况下,我认为 403 更合适,因为您无法真正解决冲突(除非删除资源的先前实例)。
对于错误消息本身,您应该修改原因短语,因此发送标头 HTTP/1.0 403 Form validation errors 是最干净的方法。
IMO,422“不可处理的实体”更有意义。我的推理是,不是服务器拒绝满足请求,而是服务器无法满足请求。
C
Community

我推荐status code 422, "Unprocessable Entity"

11.2. 422 Unprocessable Entity 422(Unprocessable Entity)状态码意味着服务器理解请求实体的内容类型(因此415(Unsupported Media Type)状态码是不合适的),并且请求实体的语法是正确的(因此400 (错误请求)状态代码不合适)但无法处理包含的指令。例如,如果 XML 请求正文包含格式正确(即语法正确)但语义错误的 XML 指令,则可能会出现这种错误情况。


当然它是一个 HTTP 状态码,参见iana.org/assignments/http-status-codes。状态代码比 RFC 2616 中定义的要多。
WebDAV 是一个 HTTP 扩展。 “Web 分布式创作和版本控制 (WebDAV) 的 HTTP 扩展” 因此,状态码 422 不是 http 状态码,而是 http 扩展的状态码。
大神,没意义。 HTTP 定义了如何定义新代码,这就是 WebDAV 正在做的事情。有一个状态代码注册表是有原因的。
仅供参考 - 422 的 RFC 描述:11.2。 422 Unprocessable Entity 422(Unprocessable Entity)状态码意味着服务器理解请求实体的内容类型(因此415(Unsupported Media Type)状态码是不合适的),并且请求实体的语法是正确的(因此400 (错误请求)状态代码不合适)但无法处理包含的指令。例如,如果 XML 请求正文包含格式正确(即语法正确)但语义错误的 XML 指令,则可能会出现这种错误情况。
并且线程不会“过期”。他们需要继续存在,否则顶级谷歌搜索结果开始变得不准确。
s
sethcall

200,300、400、500 都是非常通用的。如果你想要通用,400 就可以了。

422 被越来越多的 API 使用,甚至被 Rails 开箱即用。

无论您为 API 选择哪种状态码,都会有人不同意。但我更喜欢 422,因为我认为“400 + 文本状态”太笼统了。此外,您没有利用 JSON-ready 解析器;相比之下,带有 JSON 响应的 422 非常明确,可以传达大量错误信息。

说到 JSON 响应,我倾向于对这种情况下的 Rails 错误响应进行标准化,即:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

这种格式非常适合表单验证,我认为就“错误报告的丰富性”而言,这是最复杂的情况。如果您的错误结构是这样的,它可能会处理您所有的错误报告需求。


由 args 之间的交互引起的错误呢?也就是说,arg1 有效,arg2 有效,但两者的组合以及发送的特定值是无效的。
我不会想太多。只需选择一个似乎拥有这种关系的人。
甚至只是两个参数上的错误。作为用户,我想我想看到每个冲突字段上的错误。
好的!。显式优于隐式
A
Arsen Khachaturyan

数据库中的重复项应为 409 CONFLICT

我建议对验证错误使用 422 UNPROCESSABLE ENTITY

我对 4xx 代码 here 给出了更长的解释。


M
Marcodor

200

呃......(309、400、403、409、415、422)......很多答案试图猜测、争论和标准化对于成功的 HTTP 请求但失败的 REST 调用的最佳返回代码是什么。

混合 HTTP 状态码和 REST 状态码是错误的。

但是,我看到许多实现混合了它们,许多开发人员可能不同意我的看法。

HTTP 返回码与 HTTP Request 本身有关。 REST 调用是使用超文本传输协议请求完成的,它的工作级别低于调用的 REST 方法本身。 REST 是一种概念/方法,其输出是业务/逻辑结果,而 HTTP 结果代码是传输结果。

例如,当您调用 /users/ 时返回“404 Not found”是令人困惑的,因为它可能意味着:

URI 错误 (HTTP)

未找到用户 (REST)

“403 Forbidden/Access Denied”可能意味着:

需要特别许可。浏览器可以通过询问用户/密码来处理它。 (HTTP)

服务器上配置了错误的访问权限。 (HTTP)

您需要经过身份验证(REST)

并且该列表可能会继续出现“500 服务器错误”(Apache/Nginx HTTP 抛出错误或 REST 中的业务约束错误)或其他 HTTP 错误等...

从代码中,很难理解失败的原因是什么,是 HTTP(传输)失败还是 REST(逻辑)失败。

如果 HTTP 请求在物理上成功执行,它应该总是返回 200 代码,无论是否找到记录。因为 URI 资源已找到并由 HTTP 服务器处理。是的,它可能会返回一个空集。是否可以接收一个带有 200 作为 HTTP 结果的空网页,对吗?

取而代之的是,您可能会返回带有一些选项的 200 HTTP 代码:

如果出现问题,JSON 结果中的“错误”对象

如果未找到记录,则为空 JSON 数组/对象

布尔结果/成功标志与以前的选项相结合,以便更好地处理。

此外,一些互联网提供商可能会拦截您的请求并向您返回 404 HTTP 代码。这并不意味着找不到您的数据,而是在传输级别有问题。

Wiki

2004 年 7 月,英国电信供应商 BT Group 部署了 Cleanfeed 内容阻止系统,该系统会对 Internet Watch Foundation 确定为潜在非法内容的任何请求返回 404 错误。其他 ISP 在相同情况下返回 HTTP 403“禁止”错误。泰国和突尼斯也报道了使用虚假 404 错误作为隐藏审查的手段的做法。在 2011 年革命前审查制度严厉的突尼斯,人们开始意识到假 404 错误的本质,并创造了一个名为“Ammar 404”的虚构角色,代表“隐形审查员”。

为什么不简单地回答这样的问题?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

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 请求的。 REST API 是你的,定义你的状态码。


实际上,为 REST 使用 HTTP 状态代码在未来会更加令人困惑:1)您在开发人员的工具箱中看到 4xx,您不能只看一眼就判断服务器是否返回了一些合理的值或根本无法处理您的请求然后 2)所有错误/异常/捕获处理程序都应该检查作为响应返回的服务器(大多数情况下它们不会,因为你必须在每次服务调用时都这样做)并且很多时候 3)你得到相同的有效负载( type) 在导致复杂/重复代码的成功和错误路径上......确实非常令人困惑。
这个答案混淆了 HTTP 协议的原始语义与 REST over HTTP 作为一种架构风格如何重新利用 HTTP 来实现 Web 服务 API。作为一种架构风格,REST 不是严格遵循的标准,而是一种建议的方法。使用 200 响应验证失败并没有对错之分,但是响应请求成功但实际上由于验证失败而失败,这让您的客户感到困惑,这是响应正文中隐藏的重要细节,客户端必须解析才能理解的语义。
@Marcodor 如果您的 API 调用失败但您返回 200 表示成功,这是一个好主意吗?对于您的 API 的消费者来说,它是不清楚且令人困惑的。
正确的原因有很多,不仅仅是 HTTP 与 REST 错误的分离。 REST 验证通常需要更多细微差别。例如,接受但标记为重复的记录与因违反唯一索引而被拒绝的记录。您还需要一致的回报模型。 .NET BadRequest() 方法有自己的返回模型,它不同于您的常规返回模型。解析这是一场噩梦。 @KevinHooke,针对 REST 验证错误返回 HTTP 200 就像在说:“我收到了您的消息,答案是否定的,这就是原因。”返回 HTTP 400 说,“我不知道你在说什么。”
“因为谷歌做到了,它一定是对的”的论点对我来说是疯狂的......它可以挑战谷歌已经实现的孩子。为不成功的休息调用返回 HTTP 200 会使 API 的调用者感到困惑,它应该是 4xx,并且可以在正文中包含漂亮的 JSON/XML ......让我们一起停止疯狂。
D
Daniel Kmak

Ember-Data 的 ActiveRecord 适配器期望从服务器返回 422 UNPROCESSABLE ENTITY。因此,如果您的客户端是用 Ember.js 编写的,您应该使用 422。只有这样 DS.Errors 才会填充返回的错误。 You can of course change 422 to any other code 在您的适配器中。


S
Suncat2000

Status Code 304 Not Modified 也会对重复请求做出可接受的响应。这类似于使用实体标记处理 If-None-Match 的标头。

在我看来,@Piskvor 的答案是我认为原始问题的意图的更明显的选择,但我有一个也相关的替代方案。

如果您想将重复请求视为警告或通知而不是错误,则响应状态代码 304 Not Modified 和标识现有资源的 Content-Location 标头将同样有效。当意图仅仅是确保资源存在时,重复请求将不是错误而是确认。请求并没有错,只是简单的多余,客户端可以参考已有的资源。

换句话说,请求是好的,但是由于资源已经存在,服务器不需要进行任何进一步的处理。


据我了解,304 旨在用于 GET 操作以协助缓存。
@Sinaesthetic 这很公平,但 304 也有助于缓存。您在 a different answer 中关于使用 303 的评论本身就是一个很好的答案。
这没有任何意义。您将如何将重复请求视为非错误?您正在添加一个新资源,并得到“发现重复”响应。下一步是什么?你不加吗?然后是失败,因为意图是添加资源。如果您打算修改现有资源,请直接在该现有资源上进行,而不是尝试添加新资源。如果要检查资源是否存在,请通过查询资源来完成,而不是尝试添加新资源并检查是否返回“重复警告”。