如果请求缺少必需的参数,我应该使用啥 HTTP 状态响应代码?
Posted
技术标签:
【中文标题】如果请求缺少必需的参数,我应该使用啥 HTTP 状态响应代码?【英文标题】:What HTTP status response code should I use if the request is missing a required parameter?如果请求缺少必需的参数,我应该使用什么 HTTP 状态响应代码? 【发布时间】:2011-03-04 07:00:50 【问题描述】:我在想 412(前提条件失败)但可能有更好的标准?
【问题讨论】:
模糊相关:***.com/q/16133923/10245 412 肯定是错的 【参考方案1】:基于spec,状态 422 似乎最合适。
422 (Unprocessable Entity) 状态码表示服务器 理解请求实体的内容类型(因此 415(不支持的媒体类型)状态码不合适),并且 请求实体的语法是正确的(因此是 400 (Bad Request) 状态码不合适)但无法处理包含的 指示。例如,如果 XML 请求正文包含格式正确(即语法正确),但是 语义错误的 XML 指令。
他们指出格式错误的 xml 是一个错误语法的例子(要求 400)。格式错误的查询字符串似乎与此类似,因此 400 似乎不适用于缺少参数的格式良好的查询字符串。
更新 @DavidV 正确指出此规范适用于 WebDAV,而不是核心 HTTP。但是一些流行的非 WebDAV API 仍然使用 422,因为缺少更好的状态码 (see this)。
【讨论】:
IMO 我会在查询字符串中的值不正确时使用它,而不是在有额外值或缺失值时使用。 IE。期待一封电子邮件,其值为 '123123' 我倾向于将 GET 和 POST 参数视为 URL 路径的方法签名,因此 404 对我来说很有意义。在用于公共消费的 RESTful API 中,返回缺失/额外参数是谨慎的做法。在 URL 的上下文中,查询字符串参数通常对于识别资源很重要,额外或缺失的参数表示不存在的资源,没有任何假设。当然,通过显式来权衡健壮性,可选参数使资源可能同样容易受到静默错误的影响。然后是可用性...... 所引用的规范是针对 WebDAV 的,而不是 HTTP 标准规范。 @DavidV 你说得对,它适用于 WebDAV,但对于核心 HTTP 似乎没有更好的选择。 This blog 提到了使用 422 的流行 API。 这值得一读:bennadel.com/blog/… 我也不会使用 422 来代替缺少的参数。我觉得400
比较合适。【参考方案2】:
我不确定是否有固定标准,但我会使用 400 Bad Request,这是最新的 HTTP 规范(从 2014 年开始)documents as follows:
6.5.1。 400 错误请求
400(Bad Request)状态码表示服务器不能或 由于某些被认为是 客户端错误(例如,格式错误的请求语法、无效请求 消息框架或欺骗性请求路由)。
【讨论】:
400 Bad Request
表示协议级别的问题,而不是语义错误。如果我们要劫持 HTTP 状态码来指示应用程序级(而不是协议级)错误,为什么不直接使用412
?
Google 的 OAuth 1.0 实施同意这个答案。当 POST 参数丢失或不受支持时会给出 400 响应:code.google.com/apis/accounts/docs/OAuth_ref.html
@matt-zukowski:“412:在服务器上测试时,一个或多个请求标头字段中给出的先决条件评估为假。”来自RFC2616 - 如果是 POST,则参数在请求正文中,而不是在请求标头字段中。从技术上讲,GET 方法在请求标头中发送它的参数,但我宁愿有一些一致性?
@MattZukowski 400 是应用程序级别的状态代码。如果您查看 RFC 7231 草案版本中的重新措辞,您会看到这一点。不幸的是,最新版本中的措辞不是很清楚,因为最新更改的作者还发明了 422。
@DarrelMiller 是对的 (direct link):“400 (Bad Request) 状态码表明服务器不能或不会处理请求,因为某些东西被认为是客户端错误(例如,格式错误的请求语法、无效的请求消息帧或欺骗性请求路由)。” 取决于语义和可扩展性期望(有朝一日是否可以在没有参数的情况下发出请求?)然后只有 400和 404 在标准 HTTP 中似乎很合适。否则,为您的 API 发明新代码,但不要重载语义。【参考方案3】:
.NET 中的WCF API 在使用webHttpBinding 时通过返回HTTP 404
“未找到端点”错误来处理丢失的参数。
如果您考虑 Web 服务方法名称及其参数签名,404 Not Found
会很有意义。也就是说,如果你暴露了一个 Web 服务方法 LoginUser(string, string)
并且你请求了 LoginUser(string)
,那么后者是找不到的。
基本上,这意味着您正在调用的 Web 服务方法以及您指定的参数签名无法找到。
10.4.5 404 未找到
服务器没有找到任何匹配 Request-URI 的东西。不 指示该状况是暂时的还是 永久的。
400 Bad Request
和Gert suggested 一样,仍然是有效的响应代码,但我认为它通常用于指示较低级别的问题。它很容易被解释为格式错误的 HTTP 请求,可能是 HTTP 标头丢失或无效,或类似情况。
10.4.1 400 错误请求
由于格式错误,服务器无法理解请求 句法。客户端不应该重复请求 修改。
【讨论】:
这是 CherryPy 默认所做的。 在您接受模型并且模型的一部分丢失的情况下处理发布请求时怎么办?在这种情况下,你不会得到 404。相反,如果我没记错的话,你会得到一个无效的模型,你必须决定现在做什么。 这种解释似乎有点牵强,表达的是 RPC 而不是 REST pov。 URI 是标识符,它存在并且已经被找到。正文中发送的内容不是资源标识符的一部分。 422更合适。 404 是正确的答案,去网上编辑一些网址来寻找共识吧!【参考方案4】:您可以发送 400 Bad Request 代码。它是更通用的 4xx 状态代码之一,因此您可以使用它来表示您的意图:客户端发送的请求缺少您的应用程序正确处理它所需的信息/参数。
【讨论】:
【参考方案5】:如果所需参数中的某些内容与 API 端点所需的内容不匹配(例如密码太短),我通常会选择 422(无法处理的实体),但对于缺少的参数,我会选择 406(不可接受)。
【讨论】:
好吧,406 Unacceptable 与 Accept 标头一起使用(如果服务器无法发送响应,客户端会理解)。 “请求标识的资源只能生成响应实体,其内容特征根据请求中发送的接受标头不可接受。” .我坚持使用 422,因为当前规范没有“正确”选择:-/ 为此使用 406 是错误的。 406 代码并不意味着 request 不可接受;这意味着您无法满足请求,因为您能够提供的响应是 client 根据它在请求中发送的 Accept 标头会发现不可接受的响应。 (例如,请求包含Accept-Language: de
,表示它只接受德语响应,但您的服务器可用的请求文档的唯一版本是英语或法语。)使用它来表示请求中缺少参数不正确,根据规范中的定义。【参考方案6】:
在我们的一个 API 项目中,我们决定为某个请求设置 409 状态,但由于缺少参数而无法以 100% 填充它。
HTTP 状态代码“409 冲突”对我们来说是一个很好的尝试,因为它是定义 需要包含足够的信息让用户识别 冲突的根源。
参考:w3.org/Protocols/
因此,在 400 或 404 等其他响应中,我们选择了 409 来强制查看请求中的一些注释,这有助于设置新的正确请求。
无论如何,我们的案例都是特殊的,因为如果请求不完全正确,我们需要在前夕发送一些数据,并且我们需要强制客户端查看消息并了解请求中的错误。
一般来说,如果我们只有一些缺失参数,我们会选择 400 和一组缺失参数。但是,当我们需要发送更多信息(例如特定案例消息)并且我们希望更确定客户会处理它时,我们会发送 409
【讨论】:
这是完全错误的。 409 用于并发问题,因为@MaximeGélinas 指出了资源已经存在并且不允许重复的情况。 按照规范,“409(冲突)状态码表示由于与目标资源的当前状态冲突,请求无法完成。”。将它用于缺少的参数是错误的;这是一种完全不同的错误。【参考方案7】:对于那些感兴趣的人,Spring MVC(至少 3.x)在这种情况下返回 400,这对我来说似乎是错误的。
我测试了几个 Google 网址 (accounts.google.com) 并删除了所需的参数,在这种情况下它们通常返回 404。
我会复制谷歌。
【讨论】:
因为谷歌这样做并不意味着谷歌做对了! 我同意,不一定是“正确”,但有时正确和明智是两件不同的事情。无论如何..取决于读者:) 某些 Google API 返回 400,例如github.com/google/google-api-nodejs-client/issues/404 这是错误的(以及为什么 spring mvc 不符合 jax-rs)【参考方案8】:可以说应该使用404 Not Found
,因为找不到指定的资源。
【讨论】:
当查询参数无法转换为正确的数据类型时,这是 Java JAX-RS 的默认行为。不过我不同意。找到了资源:查询参数用于过滤资源,其中一个过滤器提供了不可接受的值。我认为这与最接近的 422 Unprocessable Entity 和最接近的 400 Bad Request 匹配。 它是 jax-rs 的默认行为,因为它是正确的行为! 当查询字符串参数用于标识资源时,使用 404 是合理的,给定了一个值,但该值与存在的资源不对应 - 例如,如果您是请求 example.com/show-user-profile?user_id=123 并且用户 123 不存在。但这不是这个问题要问的;这是关于完全省略必需参数的情况。我看不出这与未找到的指定资源有何对应。【参考方案9】:我经常使用 403 Forbidden 错误。原因是请求被理解,但我不会按要求去做(因为事情是错误的)。响应实体解释了问题所在,因此如果响应是 HTML 页面,则错误消息在页面中。如果是 JSON 或 XML 响应,则错误信息在其中。
来自rfc2616:
10.4.4 403 禁止
服务器理解请求,但拒绝执行。 授权将无济于事,并且不应重复请求。 如果请求方法不是 HEAD 并且服务器希望进行 公开为什么请求没有得到满足,它应该描述 实体拒绝的原因。如果服务器不希望 将此信息提供给客户端,状态码 404 (未找到)可以代替。
【讨论】:
一开始听起来不错,尽管我很自然地将其与身份验证或基于权限的错误联系起来。此外,规范暗示了这一点,它说“如果服务器不希望将此信息提供给客户端”。此外,404 可能是一个更好的选择。我会选择 404 或 400,而不是 403。 这是一个糟糕的主意,即使在技术上是合理的。 403 普遍用于身份验证失败响应,如果您尝试使用它来指示参数错误,您将把您的客户搞糊涂。例如,Twitter 会这样做——当你提供无效的 OAuth 凭据时,以及当你的请求出现语义错误时,都会使用 403——这对于 API 客户端来说是一个持续的混淆源。 @MattZukowski 好吧,那是错误的。规范说Authorization will not help
,所以 Twitter 不应该为无效的 OAuth 凭据发送这个。
@torvin Twitter 应该改为发送401 Unauthorized
。但是,如果您查看这两个非常相似的代码中的the MDN docs' descriptions,您就可以理解它们为什么不这样做。
您应该在回复中描述失败的原因。如果您不想这样做,只需使用 404。以上是关于如果请求缺少必需的参数,我应该使用啥 HTTP 状态响应代码?的主要内容,如果未能解决你的问题,请参考以下文章
Django - get_queryset() 缺少 1 个必需的位置参数:“请求”
行程预估请求错误 - 错误参数(缺少必需参数) - Lyft API
django,save() 缺少 1 个必需的位置参数“请求”
文件上传 AngularJS 和 Django:/uploaded_file uploadFile() 处的 TypeError 缺少 1 个必需的位置参数:“请求”