Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is curl using HTTP/1.1 rather than HTTP/2 on mac?

According to this https://curl.haxx.se/docs/http2.html

Since 7.47.0, the curl tool enables HTTP/2 by default for HTTPS connections.

Installing the latest version with homebrew and checking:

curl --version
curl 7.54.1 (x86_64-apple-darwin15.6.0) libcurl/7.54.1 SecureTransport zlib/1.2.5

but running curl on an HTTP2 enabled URL (e.g. test with https://tools.keycdn.com/http2-test) I get:

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

and

curl --http2 -v http://www.google.co.uk
curl: (1) Unsupported protocol

Any idea why it's using HTTP/1.1 rather than HTTP/2?

like image 931
Snowcrash Avatar asked Dec 24 '22 16:12

Snowcrash


2 Answers

You can build curl to use one of many different TLS/SSL libraries, each of those has slightly different feature sets and offer slightly different conditions for curl to work with.

The curl you show in your question lists SecureTransport as the TLS library it was built to use, the macOS native TLS library.

Secure Transport simply does not provide the necessary means for curl to negotiate HTTP/2 over TLS - or at least it hasn't, as I've been told that the very latest version now supports ALPN so a future curl version should be able to do HTTP/2 over TLS even with Secure Transport.

In addition to the proper TLS negotiation, curl also needs to speak HTTP/2, which it does thanks using the venerable nghttp2 library so that's a second dependency that needs to be there for curl to be able to speak HTTP/2. With nghttp2 present, curl can actually speak HTTP/2 over plain-text HTTP even when the TLS library can't negotiate ALPN properly.

Fix?

Later macOS versions ship curl built with libreSSL and HTTP/2 support built-in.

If you opt to instead rebuild curl with another TLS library, such as OpenSSL, GnuTLS or NSS it can speak HTTP/2 fine over HTTPS already today.

like image 78
Daniel Stenberg Avatar answered Dec 28 '22 07:12

Daniel Stenberg


With MacOS Sierra, this is how you can install an updated curl that supports HTTP2 by using OpenSSL instead of SecureTransport.

  1. brew reinstall curl --with-openssl --with-nghttp2
  2. brew link curl --force
  3. Relaunch Terminal
  4. curl -V should return something like this:

curl 7.54.1 (x86_64-apple-darwin16.6.0) libcurl/7.54.1 OpenSSL/1.0.2l zlib/1.2.8 nghttp2/1.24.0 Release-Date: 2017-06-14 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy

I should note that MacOS minor point updates sometimes overwrite the curl version being used. If that happens, simply re-run brew link curl --force and relaunch terminal to switch back to the homebrew HTTP2 enabled version.

like image 28
Chris Avatar answered Dec 28 '22 07:12

Chris