PUSH_PROMISE with Cowboy
The recent release of Cowboy 2.4.0 fixes the last bug I am aware of in its H2 implementation. When Phoenix 1.4 is released it will include alpha support for Cowboy 2 and thus HTTP/2 (or H2 for short).
I’ve been testing it for a while and one of the hardest things to get working was push (aka PUSH_PROMISE) support in H2.
Server push or push promise is when the server sends a client instructions to download files it knows the client will need. The client can then receive the files before parsing the page so that they are already available in the cache.
Push has been supported by Cowboy for a while but I couldn’t get it working. I tried a lot of different stuff (thats a whole other blog post) and finally I reached out to Jake Archibald from Google who pointed out that Chrome likely wasn’t trusting my “snake oil” certificate.
It turns out that even if you tell Chrome to accept your cert, you need to trust a cert with proper SAN support to get PUSH_PROMISE to work - even when working off localhost.
Simply put, you need to use SAN or push doesn’t work.
So I’ve put together instructions on how to setup your own self-signed certs with SAN support.
Self-Signed Certs with SAN using OpenSSL
Before you get started, I want to point out that I am using
test.phx.sh as my DNS name for my app.
*.dev.phx.sh have all be setup to point to 127.0.0.1 to simplify development when using certs. So you can just
your-app.phx.sh and it should just work for your app.
You need to setup a config file for openssl as it needs the config file to read in the SAN.
Here’s an example, let’s call it
I’d like to point out that your OS probably has a very specific openssl.cnf file that you should base any production
certs on. On macOS you will find it in
/System/Library/OpenSSL and it contains pretty specific config that you
should be using. This is only intended for your dev environment.
With that file in place you can simply run openssl to generate a key and cert in one swoop.
You can use the key and crt in your Cowboy config and this gets you started.
The next step is marking the cert as trusted. Double-clicking on the
.crt file should open Keychain Access where you
can mark the certificate as trusted. Open it up and there’s a dropdown where you can change the trust settings. (See
above of for a picture of it.)
This will mark the cert as trusted for Safari. You may still get a warning in Chrome but PUSH_PROMISE will now work.