我正在使用nginx/php5-fpm
代码进行测试
<?php
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
// also tested: header("Status: 404 Not Found");
echo $_SERVER["SERVER_PROTOCOL"];
并强制使用HTTP 1.0使用curl
命令。
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
正如你所见,我已经使用 发出请求HTTP 1.0
,但 nginx 回复我HTTP 1.1
赏金
@MaximDounin、@MichaelHampton 已经提供了对规范的答案,谢谢。我为未来的读者稍微扩展了这个问题:
Q. 当客户端请求 HTTP 1.0 时,响应 HTTP 1.1 有什么好处?Google 的做法不是更合理吗,即当客户端请求 1.0 时,响应 1.0?
答案1
这是正常且预期的行为,根据 RFC 2616:
至少有条件地符合此规范的应用程序应在其消息中使用 HTTP 版本“HTTP/1.1”,并且必须对任何与 HTTP/1.0 不兼容的消息这样做。有关何时发送特定 HTTP 版本值的更多详细信息,请参阅 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 协议可能会有更多版本,包括次要版本和主要版本,这些规则旨在帮助确保互操作性。谷歌对 RFC 一无所知的做法可能会失败一次HTTP/2.0已完成。(您知道它的草案形式是快闪记忆体。
答案2
问:客户端请求HTTP 1.0时响应HTTP 1.1有什么好处?
它实际上会向您发送符合 HTTP/1.0 的响应。它不会使用任何需要 HTTP/1.1 的功能(例如 keepalive)。
这样做的原因是因为这对服务器来说是一种廉价的方式来表达:
“嘿,我知道你用 HTTP/1.0 给我发了一个请求,但我只是想让你知道我是能够 HTTP/1.1. 以下是对您原始请求的回复:[...]“
(注意:如果服务器支持虚构的 HTTP/1.8,它将会响应该 HTTP/1.8。)
在某些情况下,这可以为您节省额外的请求。如果您需要从服务器获取 3 个不同的 URI,则可以将第一个 URI 发送为 HTTP/1.0,然后升级到您和服务器都支持的最高版本以进行后续请求。