HTTP状态码优先级和处理

时间:2015-06-09 19:28:28

标签: http http-status-codes rfc

假设网络应用程序收到以下请求:

POST /some/endpoint HTTP/1.1
Host: <something>
Accept: application/json
Accept-Language: pt
Content-Type: application/json
If-Match: "blabla"

Some body
  • 如果服务器不支持HTTP 1.1 ,端点/some/endpoint不存在,则应首先检查前一个问题,而应该是505而不是404回。
  • 如果恰好发生服务器端点没有接受POST 端点/some/endpoint不存在,后者应该优先,应该返回404而不是405。
  • 如果Accept无法提供,则无法对正文进行适当的解码/验证,那么406应该优先于400.

这些直觉可能就足够了。但是还有无数其他的,不清楚首先应该首选/检查两个非2XX状态代码中的哪一个。例如,如果两者都失败,应该返回Content-Type(结果为415)还是Accept-Language(406)? 415或412?就此而言...

大部分时间错误是成对独立的:如果与抛出的一个错误相关的方面(例如特定的标题值)是固定的,则另一个错误的成功/错误状态不会受到影响。在那些情况下,错误的错误&#34; priority&#34;也许只是一件令人讨厌的事。但有时情况可能是这些错误独立:我可能有一个资源如葡萄牙语的HTML,但只有英文的JSON(幽默我),所以如果客户希望我优先Accept-Language优先于Accept,而我则相反,结果会非常糟糕。

现在问题应该是显而易见的:是否有任何标准应该优先考虑哪些错误

我没有遇到任何相关的RFC,甚至是非常严肃和一般性的讨论。我知道this,这有点帮助,但主要似乎只是描述了一个特定的(深思熟虑的)实现,而不是任何标准。

2 个答案:

答案 0 :(得分:3)

显然,你不能指望这个问题得到回答“不”,即使这可能是正确答案。

所以让我来谈谈你的一个特定点:

  

我可能有葡萄牙语的HTML资源,但只有英文版的JSON(幽默我),所以如果客户希望我优先Accept-Language而不是Accept,我会做相反的事情,结果会非常糟糕。

在您的示例中,您告诉服务器葡萄牙语JSON是好的,但所有其他组合同样坏。如果情况并非如此,您可以按照以下方式详细说明您的偏好:

Accept: text/json
Accept-Language: pt, en;q=0.1

服务器可以乘以你的权重,英语JSON得1×0.1 = 0.1,葡萄牙语HTML得0×1 = 0,选择前者。

(旁注1:the registry中没有text/json媒体类型。您可能需要application/json。)

(旁注2:415 Unsupported Media Type不是您提及的方案的正确回复代码。它涉及请求正文。如果您不能尊重Accept标题,则可以回复{{3} },就像Accept-Language一样。)

答案 1 :(得分:2)

TL; DR:规范赋予服务器对其如何遵守请求的最终权限,甚至允许服务器忽略客户端请求的可接受格式。但是,规范指示服务器尽最大努力并以最能帮助客户从错误中恢复的方式进行响应。

规范提供了指导,即使他们没有(或不能)优先考虑所有可能的错误模式。

RFC 2616 § 10.4.7 says

  

允许HTTP / 1.1服务器返回响应         根据发送的接受标头不可接受         请求。在某些情况下,这甚至可能比发送一个更好         406回应。鼓励用户代理检查标题         传入的响应,以确定它是否可以接受。

RFC 7231 § 3 says

  

原始服务器可能提供或能够生成,      多个表示,每个表示旨在反映      目标资源的当前状态。在这种情况下,有些算法是      使用由原始服务器选择其中一个表示为      最适用于给定的请求,通常基于内容      协商。

RFC 7231 § 3.4 says

  

请注意,在所有情况下,HTTP都不知道资源语义。      原始服务器响应请求的一致性完全由任何实体或算法选择决定      或者生成这些回复。 HTTP不重视这个人      幕后。

RFC 7231 § 3.3 says

  

带有错误状态代码的响应消息      通常包含表示错误条件的有效负载,例如      它描述了错误状态以及建议的后续步骤      解决它。

RFC 2616 § 14.46 says

  

警告通用标头字段用于携带有关可能未在消息中反映的消息的状态或转换的其他信息。此信息通常用于警告缓存操作或应用于消息实体主体的转换可能缺乏语义透明度

(强调我的全部。)

RFC 7231的第3部分为原始服务器提供了决定适当响应的最终权限,即使该响应是令人反感的。同时,第3节鼓励原始服务器满足请求,或提供满足某些请求(Vary)的通知,或提供可选择的选项(&#34;被动协商&#34;)。

即使服务器具有最终权限,规范也会向我明确说明响应应该有助于用户解决问题。在我看来,最好的错误代码是帮助用户最好地解决问题的代码!

考虑你的配对示例:

  • &#34;如果服务器不支持HTTP 1.1并且端点/某些/端点不存在,则应首先检查前一个问题,并且应返回505而不是404 &#34;

没有。根据{{​​3}},HTTP 1.1客户端可以通过协议降级从1.0服务器GET,因此这种版本协商由规范处理。发送404(如果已知,则发送301),以便用户更正。

  • &#34;如果发生这种情况,服务器的任何端点都不接受POST,并且端点/某些/端点不存在,则后者应该获得优先级,并且应该返回404而不是405。&#34;

是的,404。如果您没有找到资源,这种方法几乎不重要。

  • &#34;如果无法提供接受且身体无法正确解码/验证,则可能406优先于400.&#34;

当你知道406适用时,永远不要发送400。您正在向客户提供较少的信息,这些信息 less 非常有帮助。但是,源服务器可以忽略每specAccept标头:

  

如果[Accept]标题字段是      出现在请求中,并且没有任何可用的表示形式      响应的媒体类型列为可接受的,      原始服务器可以通过发送406(不是      可接受的)响应或忽略标题字段通过处理      回应好像不受内容协商的影响。

  • &#34;我可能有葡萄牙语的HTML资源,但只有英文的JSON(幽默我),所以如果客户希望我优先考虑Accept-Language而不是Accept,我会这样做相反,结果将非常糟糕。&#34;

我不同意结果会很糟糕。见RFC 7231 § 5.3.2

  

原始服务器可以忽略[Accept-Language]标头字段,方法是将响应视为不受内容协商的影响,或者通过发送406(不可接受)响应来尊重标头字段。但是,不鼓励后者,因为这样做可能会阻止用户访问他们可能使用的内容(例如,使用翻译软件)。

这种规范语言模式不止一次出现。 &#34;服务器可以忽略[客户端请求的任何内容],将响应视为不受[规范的这一部分]的约束,或者服务器可以尊重[客户端请求]并发送[适用的错误代码]。但是,[发送可理解的东西]比发送[不可思议的错误代码]更好。&#34;

在一天结束时,它是您的API。 HTTP仅为您的语义提供了一个窗口。记录您接受的内容,您的回应以及内容。发送可理解的响应(HATEOAS很好),并在适用时发送可用的最具体的错误代码。