HTTP/2 behaviors with HTTP and HTTPS
Asked Answered
E

2

5

This https://en.wikipedia.org/wiki/HTTP/2#Encryption says

HTTP/2 is defined for both HTTP URIs (i.e. without encryption) and for HTTPS URIs (over TLS, where TLS 1.2 or newer is required).[25]

but testing on Google I get different results:

curl --http2 -I http://www.google.co.uk
HTTP/1.1 200 OK

curl --http2 -I https://www.google.co.uk
HTTP/2 200 

The same goes for other domains. Any explanation?

Egbert answered 10/7, 2017 at 11:56 Comment(0)
K
5

HTTP/2 can be negotiated over unencrypted channels (known as h2c) but it's more complicated as how does the client know whether the server will understand the relatively new HTTP/2 protocol? Additionally proxy servers often have problems handling new protocols like this when sent unencrypted but handle them fine when sent encrypted (because they cannot see its using a new protocol in this case).

For encrypted connections, HTTP/2 (known as h2 when encrypted) is negotiated as part of HTTPS negotiation using the ALPN extension (or the older NPN extension it has replaced) before the first HTTP request is sent.

For unencrypted connections, where there is no HTTPS negotiation, there are two options:

  1. Assume the server speaks HTTP/2 and just start talking HTTP/2 immediately. This is a bit presumptious but in theory would work if you fell back to HTTP/1 if that failed. In many ways it's similar to the discussion on making HTTPS default and falling back to HTTP - it needs critical mass to make this worthwhile.

  2. Send the initial request as a HTTP/1 request and with an upgrade: h2c HTTP Header (and a base 64 HTTP/2 settings frame as another HTTP header). This asks the server if we can switch to HTTP/2 for the next request. The server should send the HTTP/1 response with a similar upgrade header at which point the next request can be sent as a HTTP/2 request. This process is detailed in the HTTP/2 spec in section 3.2.

Curl currently only supports the second method as detailed here: https://curl.haxx.se/docs/http2.html so will not speak HTTP/2 straight away. If you run curl -v for verbose mode then you should see the upgrade headers.

However none of the mainstream web browsers support HTTP/2 over unencrypted channels (h2c) making h2 the de facto standard - at least for public facing servers intended for use by web browsers. Therefore a lot of web servers have similarly chosen not to bother implementing h2c as it will be so little used. See this page to see how few implementations support h2c. Google's servers are usually powered by GFE (Google Front End) which you can see from that list only supports h2 and not h2c.

Kamilahkamillah answered 10/7, 2017 at 12:29 Comment(0)
C
4

The reason is that all browsers decided to support HTTP/2 only in encrypted mode (h2) for various reasons.

As a consequence most tools (libraries, webservers, cli tools, etc.) also focused on supporting HTTP/2 over TLS with ALPN, and most often do not support the unencrypted variant (h2c) which either requires a HTTP upgrade or to have prior knowledge about HTTP/2.

In your case curl seems to support HTTP/2 upgrade requests, but the google webservers do not.

Crepuscular answered 10/7, 2017 at 12:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.