Nginx 忽略客户端的 HTTP 1.0 请求并通过 HTTP 1.1 响应

Rya*_*yan 8 php http nginx php-fpm

我正在测试使用nginx/php5-fpm, 与代码

<?php

header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); 
// also tested: header("Status: 404 Not Found");

echo $_SERVER["SERVER_PROTOCOL"];
Run Code Online (Sandbox Code Playgroud)

并强制在命令中使用HTTP 1.0curl

curl -0 -v 'http://www.example.com/test.php'


> GET /test.php HTTP/1.0

< HTTP/1.1 404 Not Found
< Server: nginx
< Date: Sat, 27 Oct 2012 08:51:27 GMT
< Content-Type: text/html
< Connection: close
< 
* Closing connection #0
HTTP/1.0
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我已经在请求使用HTTP 1.0,但是 nginx 回复我HTTP 1.1

赏金

@MaximDounin,@MichaelHampton 已经为规范提供了答案,谢谢。我正在为未来的读者扩展这个问题:

问:当客户端请求 HTTP 1.0 时,响应 HTTP 1.1 的优势是什么?谷歌采取的方法不应该更合理,即当客户端请求 1.0 时,用 1.0 响应?

Mic*_*ton 20

根据 RFC 2616,这是正常和预期的行为:

至少有条件地符合本规范的应用程序应该在他们的消息中使用“HTTP/1.1”的 HTTP 版本,并且必须对任何与 HTTP/1.0 不兼容的消息这样做。有关何时发送特定 HTTP 版本值的更多详细信息,请参阅 RFC 2145。

RFC 2145 对此进行了扩展

HTTP 服务器应该发送一个响应版本,该版本等于服务器至少有条件地兼容的最高版本,并且其主要版本小于或等于请求中收到的版本。HTTP 服务器不得发送至少不符合条件的版本。如果无法使用客户端请求中使用的主要版本发送响应,服务器可以发送 505(不支持 HTTP 版本)响应。

如果知道或怀疑客户端错误地实现了 HTTP 规范,HTTP 服务器可以发送较低的响应版本,但这不应该是默认值,如果请求版本是 HTTP/1.1 或更高版本,则不应这样做。

这在英文中的意思是:如果客户端发送 HTTP/1.0 请求,则 HTTP/1.0 响应或 HTTP/1.1 都可以接受,但首选 HTTP/1.1。

这样做的原因是,一端可以通告它可以支持的最高版本的 HTTP,以便另一端可以选择升级其协议支持(如果可能)。然后两端将决定他们都可以使用的协议版本。正如 RFC 2145 所述,这种设计还有助于处理有缺陷的实现。

当时还设想可能会有更多版本的 HTTP 协议,包括次要和主要版本,这些规则旨在帮助确保互操作性。一旦HTTP/2.0最终确定,Google 的 RFC 无知方法可能会失效。(你知道它的草稿形式是SPDY。)

  • 不,nginx 永远不会将响应版本降级到 1.0。另一方面,它不会使用 HTTP/1.0 中不可用的协议特性。例如,它不会尝试保持连接活动,也不会使用分块传输编码。 (5认同)
  • 它符合 RFC 2145,并允许客户端在没有额外请求的情况下找出服务器支持的 HTTP 版本。如果您仍然觉得它令人困惑,您可能需要重新阅读 RFC 2145。 (5认同)

mh.*_*mh. 6

问:当客户端请求 HTTP 1.0 时,响应 HTTP 1.1 的优势是什么?

它实际上向您发送了一个符合 HTTP/1.0 的响应。它不会使用任何需要 HTTP/1.1 的特性,例如 keepalive。

这样做的原因是因为它是服务器说的一种廉价方式:

“哎,我知道你使用HTTP / 1.0送我的请求,但只是为了让你知道我AM能够HTTP /的1.1和这里的你原来的请求的响应:[..]

(注意:如果服务器支持虚构的 HTTP/1.8,它会响应。)

在某些情况下,这可以为您节省额外的请求。如果您需要从服务器获取 3 个不同的 URI,您可以将第一个作为 HTTP/1.0 发送,然后升级到您和服务器都支持后续请求的最高版本。