On a global purpose of optimisation of my website, I lately added some features and enhanced the HTTP2 delivery of the website. The performance restults are instantaneous. But, as there is always a but, it generated some random issues … with Google Chrome (and it’s opensource pendant, Chromium).
The consequence of the bug was a almost random “Aw, Snap !” page : every time I clicked on an internal link or upon one load out of two. And only with Chrome and Chromium. First asumption as it only occurs with a specific browser, it was a code issue : either HTML or, more probably, JS. I started debugging the code with no luck about this one. I decided to create two very simple HTML page with just a basic HTML link towards each other. Again, no luck.
Then, I guessed : when I get the “Aw, Snap” page, the DevTools in Chrome report just nothing besides the SSL details. No URI called. No JS console. Nothing else. So, I decided to debug the SSL part. A review thanks to Qualys reported no issue and even granted an A score to the website (via the CDN and via the origin also). As the late changes were about HTTP2, I decided to test the HTTP2. First, I disabled it from the CDN side. But as the page was in cache, no change resulted from this. Then I debugged the HTTP2 using several tools as h2i or h2c. Again, every thing when fine.
So, I decided to go through the web (GIMF). I found pages about the NPN not being supported any more by Google, so I decided to update my nginx, by recompiling it against openssl 1.0.2 instead of the basic openssl 1.0.0 branch as it is from the various defaut packages ; this enabled the ALPN but did not solve my case. Then, I review my whole nginx config, to check about all the HTTP2 settings. Testing one by one. And … I found it :
Link: </images/banner-1024x240.jpg>; rel=preload; as=image
And there we are : removing this HTTP header from the delivery of HTML pages solved it all. Now this header might not seems harmful. This is one of the new Headers from HTTP2 : it enables the Server Push, meaning, once the HTTP2 connection is opened, the server will push this connect, to preload the image at the same time it push the HTML code. Great for performance optimisations. But, it has a but …
Even if HTTP2 is a new standard, it still relies on a bunch of draft for the different features and headers. The one for the preload of content thanks to Server Push, is still in an early stage. Also, in nginx, this requires to be set by the upstream, meaning your application server behing nginx. And this was my error: as I publish HTML only (thanks to Jekyll), I don’t have any upstream to nginx. So when I was working on the HTTP2 optimisations, I set the Server Push header directly in the nginx configuration, thanks to add_header. For sure, the header was present and reported no error on the debug tools and most of the browsers. But this leveraged a race condition in Chrome.