Please enable Javascript to view the contents

 ·  ☕ 6 分钟

Negotiation

HTTP 1.1 plain text Upgrade header

https://http2-explained.haxx.se/en/part5#5.1.-http2-for-existing-uri-schemes

As mentioned already, the existing URI schemes cannot be modified, so http2 must use the existing ones. Since they are used for HTTP 1.x today, we obviously need a way to upgrade the protocol to http2, or otherwise ask the server to use http2 instead of older protocols.

HTTP 1.1 has a defined way to do this, namely the Upgrade: header, which allows the server to send back a response using the new protocol when getting such a request over the old protocol, at the cost of an additional round-trip.

That round-trip penalty was not something the SPDY team would accept, and since they only implemented SPDY over TLS, they developed a new TLS extension which shortcuts the negotiation significantly. Using this extension, called NPN for Next Protocol Negotiation, the server tells the client which protocols it knows and the client can then use the protocol it prefers

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade

The HTTP 1.1 (only) Upgrade header can be used to upgrade an already established client/server connection to a different protocol (over the same transport protocol). For example, it can be used by a client to upgrade a connection from HTTP 1.1 to HTTP 2.0, or an HTTP or HTTPS connection into a WebSocket.

https://httpwg.org/specs/rfc7540.html#discover-http

1
2
3
4
5
GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

Note: Connection: upgrade must be set whenever Upgrade is sent.

The server can choose to ignore the request, for any reason, in which case it should just respond as though the Upgrade header had not been sent (for example, with a 200 OK).

If the server decides to upgrade the connection, it must:

  1. Send back a 101 Switching Protocols response status with an Upgrade header that specifies the protocol(s) being switched to. For example:

Response:

If the server does not support the new protocol, it will simply respond to the client using HTTP/1.1:

1
2
3
4
HTTP/1.1 200 OK
Content-length: 243
Content-type: text/html
...

If the server switches to the new protocol, it will signal so via a 101 response. The server switches to HTTP/2.0 immediately after the empty line which terminates the 101 response [I-D.ietf-httpbis-p2-semantics].

1
2
3
4
5
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...
  1. Send a response to the original request using the new protocol (the server may only switch to a protocol with which it can complete the original request).

Ref.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism
https://tools.ietf.org/id/draft-montenegro-httpbis-http2-negotiation-00.html

Starting HTTP/2 with Prior Knowledge

https://httpwg.org/specs/rfc7540.html#known-http

A client can learn that a particular server supports HTTP/2 by other means. For example, [ALT-SVC] describes a mechanism for advertising this capability.

A client MUST send the connection preface (Section 3.5) and then MAY immediately send HTTP/2 frames to such a server; servers can identify these connections by the presence of the connection preface. This only affects the establishment of HTTP/2 connections over cleartext TCP; implementations that support HTTP/2 over TLS MUST use protocol negotiation in TLS [TLS-ALPN].

Likewise, the server MUST send a connection preface (Section 3.5).

Without additional information, prior support for HTTP/2 is not a strong signal that a given server will support HTTP/2 for future connections. For example, it is possible for server configurations to change, for configurations to differ between instances in clustered servers, or for network conditions to change.

http2 negotiation over TLS(ALPN)

https://http2-explained.haxx.se/en/part5#5.3.-http2-negotiation-over-tls

Next Protocol Negotiation (NPN) is the protocol used to negotiate SPDY with TLS servers. As it wasn’t a proper standard, it was taken through the IETF and the result was ALPN: Application Layer Protocol Negotiation. ALPN is being promoted for use by http2, while SPDY clients and servers still use NPN.

The fact that NPN existed first and ALPN has taken a while to go through standardization has led to many early http2 clients and http2 servers implementing and using both these extensions when negotiating http2. Also, NPN is what’s used for SPDY and many servers offer both SPDY and http2, so supporting both NPN and ALPN on those servers makes perfect sense.

ALPN differs from NPN primarily in who decides what protocol to speak. With ALPN, the client gives the server a list of protocols in its order of preference and the server picks the one it wants, while with NPN the client makes the final choice.

Ref. https://matthewparrilla.com/post/negotiation-http2-alpn-tls-handshake/

Misc FAQ

Can I implement HTTP/2 without implementing HTTP/1.1?

https://http2.github.io/faq/

Yes, mostly.

For HTTP/2 over TLS (h2), if you do not implement the http1.1 ALPN identifier, then you will not need to support any HTTP/1.1 features.

For HTTP/2 over TCP (h2c), you need to implement the initial upgrade request.

h2c-only clients will need to generate an OPTIONS request for “*” or a HEAD request for “/”, which are fairly safe and easy to construct. Clients looking to implement HTTP/2 only will need to treat HTTP/1.1 responses without a 101 status code as errors.

h2c-only servers can accept a request containing the Upgrade header field with a fixed 101 response. Requests without the h2c upgrade token can be rejected with a 505 (HTTP Version Not Supported) status code that contains the Upgrade header field. Servers that don’t wish to process the HTTP/1.1 response should reject stream 1 with a REFUSED_STREAM error code immediately after sending the connection preface to encourage the client to retry the request over the upgraded HTTP/2 connection.

HTTP/2 Version Identification

https://httpwg.org/specs/rfc7540.html#versioning

  • h2” identifies the protocol where HTTP/2 uses Transport Layer Security (TLS) [TLS12]. This identifier is used in the TLS application-layer protocol negotiation (ALPN) extension [TLS-ALPN] field and in any place where HTTP/2 over TLS is identified.

    The “h2” string is serialized into an ALPN protocol identifier as the two-octet sequence: 0x68, 0x32.

  • h2c” identifies the protocol where HTTP/2 is run over cleartext TCP. This identifier is used in the HTTP/1.1 Upgrade header field and in any place where HTTP/2 over TCP is identified.

    The “h2c” string is reserved from the ALPN identifier space but describes a protocol that does not use TLS.

Summary

As previously mentioned, for plain-text HTTP 1.1 the way to negotiate http2 is by presenting the server with an Upgrade: header. If the server speaks http2 it responds with a “101 Switching” status and from then on it speaks http2 on that connection. Of course this upgrade procedure costs a full network round-trip, but the upside is that it’s generally possible to keep an http2 connection alive much longer and re-use it more than a typical HTTP1 connection.

While some browsers’ spokespersons stated they will not implement this means of speaking http2, the Internet Explorer team once expressed that they would - although they have never delivered on that. curl and a few other non-browser clients support clear-text http2.

Today, no major browser supports http2 without TLS.

分享

Mark Zhu
作者
Mark Zhu
An old developer