Upgrading phoenix framework to serve http2
Http2 is the next version of the http protocol and offers several advantages. It serves over a single connection, reducing the number of roundtrips necessary. With multiplexing it can handle multiple requests at the same time and as a whole is just better.
As the internet slowly moves to support http2, Phoenix does not lag behind. The webserver Phoenix uses, Cowboy, has released version 2 with support for http2 and the updates to Phoenix and Plug have followed in its path. If you’re curious as to how you can upgrade your phoenix/plug application to also serve over http2 please continue.
First, let’s create a minimal phoenix application.
mix phx.new --no-brunch --no-ecto http2_test
We leave out ecto and brunch for simplicity. If you open this in your browser by starting the server with mix phx.server
,
you’ll see the new app, in the network tab of the chrome developer tools you can see it is served over http.
Open up the mix.exs
file and replace the dependencies with this:
defp deps do
[
{:phoenix, git: "https://github.com/phoenixframework/phoenix", branch: "master", override: true},
{:plug, git: "https://github.com/elixir-plug/plug", branch: "master", override: true},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_html, "~> 2.10"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 2.1", override: true},
]
end
The changes are that we use Cowboy 2.1, instead of 1.0 and furthermore we use the latest versions of phoenix and plug from their respective master branches on github.
Run mix deps.get
to retrieve the new dependencies.
Next up is preparing the app itself, I will only deal with the dev environment but it should apply in other environments as well.
Open config/dev.exs
, there should be a commented line telling you to generate a private key and self signed certificate. We will need to do this as, although http2 does not specifically require it, browser do expect http2 connections to be secured over TLS.
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout priv/server.key -out priv/server.pem
Add the two generated files to .gitignore.
Now we will need to adjust the Endpoint configuration to use a secure connection and use a Cowboy 2 handler
Replace the configuration with the following.
config :http2_test, Http2TestWeb.Endpoint,
debug_errors: true,
handler: Phoenix.Endpoint.Cowboy2Handler,
code_reloader: true,
check_origin: false,
watchers: [],
https: [port: 4000, keyfile: "priv/server.key", certfile: "priv/server.pem"]
This tells phoenix to listen on port 4000 with the just generated certificate. Furthermore, the handler tells Phoenix to use Cowboy2.
If you now start the application with mix phx.server
and go to https://localhost:4000
the browser will tell that the connection is not secure with for example NET::ERR_CERT_AUTHORITY_INVALID
. This is because the certificate is self signed, and not by a certificate authority. You can open the certificate in for example Keychain on Mac OS X and tell your OS to trust the certificate.
If you try again, the browser should accept the certificate and the connections should be using http2. If you look in the network tab of the developer tools it should mention h2
in the protocol column.
See https://github.com/maartenvanvliet/phoenix_http2 for the code of this post
To learn how to split assets in webpack and utilize multiplexing in http2 see this article: https://chase.pursu.es/http-2-today-with-phoenix.html
Photo by Drew Hays on Unsplash