Pragmatism in the real world

Using HTTP/2 with PHP 7 on Mac

if you want to use HTTP/2 with PHP on OS X, you need a version of curl compiled with HTTP/2 support. You can then link your PHP’s curl extension to this version.

The easiest way to do this is to use Homebrew:

$ brew install openssl
$ brew install curl --with-nghttp2
$ brew install php70 --with-homebrew-curl

At the time of writing, this will install PHP 7.0.10 with Curl 7.50.1:

$ php -i | grep cURL
cURL support => enabled
cURL Information => 7.50.1

Using Curl on the command line

If you want to use your shiny new curl from the command line, then the easiest way to do this is:

brew link curl --force

You can now do:

$ curl -V

and you should get:

curl 7.50.1 (x86_64-apple-darwin15.6.0) libcurl/7.50.1 OpenSSL/1.0.2h zlib/1.2.5 nghttp2/1.14.0
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

(at the time of writing!)

Using Guzzle to test HTTP/2 is working

To prove it works in PHP, use Guzzle!:

$ composer require guzzlehttp/guzzle


require_once 'vendor/autoload.php';

$client = new GuzzleHttp \Client();
$response = $client->get('', [
    'version' => 2.0,
    'debug' => true,

Run this PHP code at the command line:

$ php testhttp2.php

As we’ve turned on debugging, the output looks like this:

* Rebuilt URL to:
*   Trying
* Connected to ( port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /usr/local/etc/openssl/cert.pem
  CApath: none
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=*
*  start date: Aug 17 18:56:43 2016 GMT
*  expire date: Nov  9 18:29:00 2016 GMT
*  subjectAltName: host "" matched cert's "*"
*  issuer: C=US; O=Google Inc; CN=Google Internet Authority G2
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fa804802000)
> GET / HTTP/1.1
User-Agent: GuzzleHttp/6.2.1 curl/7.50.1 PHP/7.0.10

* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< date: Sun, 28 Aug 2016 10:36:13 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-1
< p3p: CP="This is not a P3P policy! See for more info."
< server: gws
< x-xss-protection: 1; mode=block
< x-frame-options: SAMEORIGIN
< set-cookie: NID=85=UrPdiR04M5ZzIUtj4sZMPRZbY8vZEKVvazZy59PpoO5NG29lVX7JNuaeiajLhDKHiEBF2tWev3yj0xFF7fvYChmARVsFSnfiBX06ewWnMaPeXy0KkneQJ7dmHGS7JYaz; expires=Mon, 27-Feb-2017 10:36:13 GMT; path=/;; HttpOnly
< alternate-protocol: 443:quic
< alt-svc: quic=":443"; ma=2592000; v="35,34,33,32,31,30"
< accept-ranges: none
< vary: Accept-Encoding
* Connection #0 to host left intact

The key things to notice:

* ALPN, offering h2
* ALPN, offering http/1.1

We tell the server that we want HTTP/2 (h2), but can accept HTTP/1.1. If the server doesn’t support HTTP/2 it will send back HTTP/1.1

Using HTTP2, server supports multi-use

This is a good sign!

The response’s status line is:

HTTP/2 200

The version number is 2 and we got a 200, so all is OK!

Everything is working as intended.

One thought on “Using HTTP/2 with PHP 7 on Mac

  1. maybe this is a little bit wrong?

    " If the server doesn't support HTTP/2 it will send back HTTP/1.1”

    shouldnt it be " If the client doesn't support HTTP/2 the server will send back HTTP/1.1” ?

    Otherwise thanks for trying this out, I believe it will help many people!

Comments are closed.