多个协议 - 正确实施

Multiple Protocols - Correct Implementation

我正在检查我的浏览器和 Google 之间的一些 HTTP 交换,它触发了这个问题。

简而言之,我的浏览器 (Firefox 36.0.4) 正在发出 HTTP/1.1 请求,而 Google 正在响应 HTTP/2.0;没有尝试在请求的协议中做出响应。我知道很多 HTTP/2.0 规范已经通过 SPDY 以随意的方式实现,但这似乎与客户的协商不佳。

我认为在 header 中声明协议的目的是服务器能够确定它应该如何响应客户端,这是在三种方式之一:

1. the client has requested the server's preferred protocol, so the server continues with the request as normal

2. The client has requested another protocol version that the server supports, the server responds in the request protocol but includes an upgrade header indicating its preferred protocol. The client MAY request an upgrade at which point the server will send a 101 Switching Protocols response and switch to the preferred protocol.

3. The client has requested an unsupported or outdated protocol, the server sends a 426 Upgrade Required response with supported protocols (in descending order of preference) in the upgrade header; the client must repeat the request with a supported protocol.

4. The client reuested a major protocol version that is wholly unsupported; e.g. HTTP/2.x while the server only supports HTTP/1.x. The server responds with 505 HTTP Version Not Supported

与Google的交流不是这样做的;这是糟糕的做法还是我遗漏了什么?

一个例子,随机选择:

https://plus.google.com/u/0/_/notifications/frame?querystring=blahblahblah

GET /u/0/_/notifications/frame?querystring=blahblahblah HTTP/1.1
Host: plus.google.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://www.google.co.uk/?gfe_rd=cr&ei=Lc8bVcXFOKbj8we_uIKYDg&gws_rd=ssl
Cookie: NID=67=iZxcMVTvg-6PsQIUpZ5tSPL-7-uJdls3vdci3afLmoLCpD5JOq0NfzhTnnpcCW9ymbXsn3GRGxfSgYlXGEk9XmnbUne0LCPrUc_ahhpc5wV6n-GZ8F7s-JS-JWgZWEwri-GaWXK1vgyRw7jMbqEiAUSRCzs1Fr1K6ZUIH0EpJdlwZD-K26MJNazpyHL_vZ5k4m8NrtFDkAoYPw; OTZ=2759671_52_56_123900_52_436380; SID=DQAAAP0AAAAqKgGz5aFNESd464Z_jUsmTi7JQfEKsuWkGZVJe8QvdbOPTZpL5ZNjKSsSSg9QvJglP-aMNLrgn2b7MsDF_4Z7Ebe1X347Cd3-j3ktLedgmq9nRO92hxEseqf974VNumrst-XqMj9Oq_xf-KDz-CDEJ1XiqWZYVHurV-IrXib5ei7x9dqlLF2NSPYLaCxlrwKdjCQX-FDDB03FWEuE7dIMYs3BQ-_NU5fG9os6I6r6ABy9mkiy84rraZFVthd38VJF5z2WYmgQ55QJPr9EDpSA5VKH1tbW6XyLjZLt5EEEj1xoqRF4EguRkIOiG8IiqRs49GnwqQSCpTw3ROW-jNDI; HSID=A7u8vyQI-v7jJSEbS; SSID=AOojY4hDLYgnSjUrK; APISID=z23KH1a0VsBukvMu/ARaOeOni08HfbGg6R; SAPISID=5iTgyxKDRPP7fNtF/AdiFbKNYN04h7n6cu; PREF=ID=cc54787f58f50d42:U=8e10581450dbe3b5:FF=0:LD=en:TM=1416091562:LM=1418086819:GM=1:S=0KVfl2hqkG8Psvwv; OGP=-5061451:-5061492:; OGPC=4061155-1:
Connection: keep-alive

HTTP/2.0 200 OK
Alternate-Protocol: 443:quic,p=0.5
Cache-Control: private, max-age=0
content-security-policy-report-only: script-src 'unsafe-inline' 'unsafe-eval' 'self' https://*.googleapis.com https://*.gstatic.com https://apis.google.com https://www.google-analytics.com https://www.googletagmanager.com https://*.talkgadget.google.com https://pagead2.googleadservices.com https://pagead2.googlesyndication.com https://tpc.googlesyndication.com https://s.ytimg.com https://www.youtube.com https://clients1.google.com https://www.google.com;report-uri /_/cspreport/es_oz_20150330.18_p0
Content-Type: text/html; charset=utf-8
Date: Wed, 01 Apr 2015 10:57:55 GMT
Expires: Wed, 01 Apr 2015 10:57:55 GMT
Server: GSE
x-content-type-options: nosniff
x-ua-compatible: IE=edge, chrome=1
X-XSS-Protection: 1; mode=block
X-Firefox-Spdy: h2-15

响应中的 HTTP 版本是服务器功能的广告,而不是响应的实际协议版本。 响应的协议版本是随请求一起发送的协议版本。

过去(但现在可能也是如此)老客户端发送 HTTP/1.0 请求并让服务器以这种方式响应是很常见的:

GET / HTTP/1.0
User-Agent: Netscape/1.0

HTTP/1.1 200 OK
Content-Length: 0

<connection closed>

服务器通告它可以说 HTTP/1.1,但在响应中表现得像 HTTP/1.0(通过关闭连接)。

同样的情况也发生在你的情况下:你发出一个 HTTP/1.1 请求,服务器通告它可以说 HTTP/2.0 并以 HTTP/1.1 响应响应格式。

收到该响应的智能客户端可以开始与该服务器对话 HTTP/2.0。

这是一个 https 请求。客户端宣布支持 HTTP/2.0,并在 SSL 握手中使用 ALPN(以前称为 NPN)扩展。因此服务器知道客户端可以做HTTP/2.0。如果未给出此扩展,则不允许服务器使用比客户端请求更高的主要 HTTP 版本进行回复。