Update: The PR’s discussed in this blog post have been merged. You can try out Early Hints by using Rails and Puma master. You’ll need to also use Arel master until Rails 5.2 is released.
Recently I’ve been working with Aaron Patterson on implementing the HTTP2 Early Hints.
The spec for Early Hints is still in draft but explains the requirements for implementation. In order to start preparing Rails and Rack for HTTP2 we’ve implemented Early Hints handling in Puma and Rails.
As of today (September 29, 2017) the pull requests haven’t been merged but we’d love for you to try them out if you’re interested in implementing Early Hints. A lot of this work is somewhat experimental so try it on production at your own risk.
In this post I’ll go over what early hints are, what the spec expects, and finally how to use the two pull requests to test it out on your own application.
Early Hints, what huh?
The Early Hints spec contains header Links with references to those resources that you need downloaded early. An example response from the server looks like this:
HTTP/1.1 103 Early Hints Link: </style.css>; rel=preload; as=style Link: </script.js>; rel=preload; as=script HTTP/1.1 200 OK Date: Fri, 26 May 2017 10:02:11 GMT Content-Length: 1234 Content-Type: text/html; charset=utf-8 Link: </style.css>; rel=preload; as=style Link: </script.js>; rel=preload; as=script
There are 2 responses, one for Early Hints that sends the linked resources and one for the final request that should also include the same links.
For the Link header,
Link: </style.css>; rel=preload; as=style the
style.css is the path to the css file,
rel does not change and should be
as is the type of resource you’re sending. The
as is not required, but is useful for content-security policies.
While HTTP/1.1 can accept a 103, a server might not actually send the hints unless it absolutely knows they will be accepted. HTTP/2 is less likely to have this problem as handling of response headers doesn’t affect how the response body is determined (as noted in the spec.
Implementing Early Hints with Puma and Rails
Below I’ll describe how you can try these two out in your Rails app. First make sure you’re using the Rails and Puma gems set to the branch for these PRs’
# Gemfile gem 'rails', git: 'https://github.com/eileencodes/rails', branch: 'early-hints' gem 'puma', git: 'https://github.com/eileencodes/puma', branch: 'early-hints' gem 'arel', git: 'https://github.com/rails/arel'
Next you’ll need a proxy that can handle HTTP/2.
Install h2o via homebrew or the method you need for your computer. I used homebrew with
brew install h2o.
Find the h2o config file (mine is in
/usr/local/etc/h2o/h2o.conf and update it with the following:
hosts: "localhost": listen: port: 9090 ssl: certificate-file: /usr/local/etc/h2o/localhost.crt key-file: /usr/local/etc/h2o/localhost.key paths: "/": proxy.reverse.url: "http://127.0.0.1:3000/" access-log: /usr/local/var/h2o/access-log error-log: /usr/local/var/h2o/error-log
Next you’ll need a “fake” certificate so you can do HTTPS requests with localhost. Otherwise Early Hints won’t work. See this post for more information on the following.
Run this command:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt
And follow the prompts. I hit
enter for everything. Then move your certificate and key into your h2o folder since that’s where the config is looking. If you want the cert to live somewhere else, update your h2o.conf with that new path.
Now start the h2o server with the config:
h2o -c h2o/h2o.conf
And start your Rails server (if it’s a Rails 5 app you will automatically be using Puma. This will not work if you’re not using the Puma branch I linked above):
bin/rails s --early-hints
Open Chrome and go to
someurl with a URL you know uses a
stylesheet_link_tag because that’s the way Early Hints is currently implemented in Rails.
Open the Chrome dev tools and go to the network tab. From there you should see
Push / posts where
posts is the URL you entered under the “Initiator” column. Below is a screenshot of my Chrome dev tools showing the Early Hints loading. If you click the image to load the full side it is easier to view.