2

This is my first question here, hope I'm doing it right.

I'm using a LiteSpeed webserver with HTTP/2 (shared hosting provider), but I can't get the push feature to work. I'm not quite sure how to check if it works, but at least as far as I can tell it isn't working properly.

So I have looked up a ton of guides (HTTP/2 Server Push Tutorial or A Comprehensive Guide To HTTP/2 Server Push as examples), and they all mention changing the headers by adding the following:

link: </my/theme/css/style.css>; rel=preload; as=style

I understand that this code tells the server to preload said resource, in this case style.css. However, if the server supports HTTP/2 push, then it should automatically push the resource instead (as long as you don't add nopush at the end of it). The second link does mention that this is true for most, but not all servers.

So with this in mind, I created a simple test PHP page to see if I could get it working. The result was this:

Chrome DevTools showing Headers tab with link preload

Network tab in DevTools showing the result

So most of the guides I saw mentioned that the Initiator in the Network tab for the pushed resource would say Push / Other (or similar) instead of just Other, but as you can see from my result it just says Other. Not to mention that the resource doesn't get loaded in the same request, it just looks like a simple preload to me. I also tested my site with https://http2.pro/check, and it says no resource is pushed.

This was tested with Chrome 71.0.3578.98.

  • Am I missing something important here? Could it be a problem with my server?
  • Another question. When defining multiple resources in the headers for preload and push, some guides mention creating multiple link-elements, while others mention comma separating them in a single link-element. Are both of these correct, is one better than the other?

Any help or enlightenment is appreciated, thanks!

dpkdawg
  • 23
  • 1
  • 5
  • Can you add a `curl --http2 -v your.server.net` output? – Pinke Helga Jan 13 '19 at 00:56
  • Where would I run this command? – dpkdawg Jan 13 '19 at 01:47
  • In the system console (terminal window), e.g. Bash CLI. On Windows there should be some download of a curl implementation. `wget2` is an alternative to curl. Or any other way to show the entire raw response incl. all headers and HTTP version. – Pinke Helga Jan 13 '19 at 01:56
  • As I read the tutorials HTTP2 is required to get it work. I will not be able to answer your question, however, other people will probably need that raw information to locate the problem. – Pinke Helga Jan 13 '19 at 02:00
  • Ate you using a self-signed cert (i.e. do you have a red padlock or a grey padlock)? Does it work in Firefox? – Barry Pollard Jan 13 '19 at 09:18

3 Answers3

1

First of all you need to find out if your infrastructure uses Link headers to activate push. Litespeed documentation doesn't seem great here but let's assume that is how you activate push.

Next is to check if your server is sending the pushed request. I find nghttp the best tool to do this so if you have access to this too, then run a command like this to see the HTTP/2 frames and if the PUSH_PROMISE frame is sent, indicating the style sheet is being pushed:

nghttp -anv https://www.example.com

You can also see the frames using Chrome, though they've just made this a lot harder but insisting on logging to disk first and then opening in a viewer. Follow the instructions similar to @LucasRolff's answer, but for HTTP/2 or here.

Assuming the server is pushing the resource you're next left with why Chrome is not using that pushed resource. The most common reason is if you are using a self-signed TLS certificate to provide HTTPS that the browser does not recognise. Even if you click through the error and get a connection with a red padlock, Chrome will not use the cache for that connection, and so cannot use HTTP/2 push (which requires using the HTTP/2 push cache). The nghttp or Chrome event log output should show if this is the case. Alternatively try using Firefox which DOES allow HTTP/2 push to be used if unrecognised certificates are clicked through.

Finally to your last question:

When defining multiple resources in the headers for preload and push, some guides mention creating multiple link-elements, while others mention comma separating them in a single link-element. Are both of these correct, is one better than the other?

Both are correct. HTTP (whether HTTP/1.1 or HTTP/2) defines this:

header1: value1
header1: value2

and this:

header1: value1, value2

as syntactically identical:

A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma.

Community
  • 1
  • 1
Barry Pollard
  • 40,655
  • 7
  • 76
  • 92
  • Thanks for answering both of the questions! I'd give the answers here +1, but unfortunately I need more rep to do so. The log to disk feature seems pretty good, I didn't know such a thing existed. According to my log it does say that 3 resources were pushed and claimed (style.css and the 2 font files), so I assume this means that it works as intended? I'm still confused as to why DevTools shows it the way it does for me. – dpkdawg Jan 17 '19 at 17:52
  • Seems odd. Try my website (https://www.tunetheweb.com) and see what it does as it has a pushed resource and shows "Push / Other" for me. Or give you URL and can have a quick look for you. – Barry Pollard Jan 17 '19 at 17:59
  • This is weird. For your site I'm not getting anything pushed, not even in the logs. I'd love to share my URL, but I can't share it here. – dpkdawg Jan 17 '19 at 18:28
  • Clear your cookies and restart your browser. I use a couple of techniques to avoid pushing the resource again if I’ve already sent it. Including this cookie based technique: https://www.tunetheweb.com/performance/http2/http2-push/ and Apache remembering past pushes on a connection. – Barry Pollard Jan 17 '19 at 18:31
  • Alright, that makes sense! Yes, it does show Push / Other for me, and the result does look as expected with Receiving Push and Reading Push, instead of the usual Request sent, Waiting and Content Download in the Network tab of Chrome. – dpkdawg Jan 17 '19 at 18:42
  • Okay so I've just had a breakthrough. I tested some different settings and noticed that when I turned off Optimize Website in cPanel (compression using mod_deflate module), then everything worked perfectly. My Network tab now shows Push / Other, and the files are indeed beeing pushed. I don't know if this is intended or not, but it seems like compression with mod_deflate has been at least part of the issue. I have Brotli enabled on my server, don't know if this could have anything to do with it. I tried enabling compression in .htaccess instead, and the same thing happens. – dpkdawg Jan 18 '19 at 00:11
1

Sorry to inform you, but HTTP/2 Push is deprecated and no longer used. See: https://developer.chrome.com/blog/removing-push/

0

So there can be a few things after some testing with various configurations, browser versions and flags enabled/disabled within Chrome as well as investigating with the network event viewer.

If the LiteSpeed Web Server has QUIC enabled, Chrome v71 seems to be showing the request as a normal GET request, and won't indicate it being pushed, however looking in the network event viewer in Chrome, it reveals that it indeed is pushed (Look for QUIC_SESSION_PUSH_PROMISE_RECEIVED).

Now, this will only be the case if QUIC in the browser is enabled as well, which it isn't by default currently in Chrome v71 as far as I can tell (they disable and enable things from time to time) - so you either have to have a flag set in Chrome to enable QUIC and you'll see the above behavior (You should also see http/2+quic/43 in "Protocol" under web developer tools).

If QUIC isn't enabled in the Browser or on the web server, you should see the file being pushed, and Chrome v71 would indicate this with the Initiator "Push / Other".

Now, in Chrome v73 (Canary release), it will have the "Initiator" set to Other and the "Size" should be (from memory cache), this indicates the file being pushed.

In Google Chrome you can go to chrome://net-export/ and click "Start Logging to Disk", then refresh your browser window where you have the file that expects to be pushed - stop the measurement, and go to https://netlog-viewer.appspot.com/ - import the json file here, and go to "QUIC", find your domain name in the list, and click on the "Connection ID".

Then click the "QUIC_SESSION" in the list, and search for QUIC_SESSION_PUSH_PROMISE_RECEIVED - if there's matches, you know for a fact that the files are pushed.

It's a bit of digging to figure out whether it's pushed currently, and the confusion is mainly related to Chrome Dev Tools not really being consistent between protocols and versions.

LucasRolff
  • 1,228
  • 3
  • 11
  • 20
  • The screenshots from OP show he is using h2 not QUIC. Also not sure I agree with your Canary comment. Just tested and it still shows "Push / Other" for correctly pushed resources. – Barry Pollard Jan 14 '19 at 20:01
  • Alright so I've checked a few things now. QUIC is enabled by the server, but as @BarryPollard stated my browser was using h2 and not QUIC. According to you that means I should see "Push / Other", but I'm just seeing "Other". This is still with Chrome V71. I asked my hosting provider, and they said that push was active and working on my site, but it doesn't make sense to me. If push was active and working my browser wouldn't show the initiator as Other, and the style.css wouldn't have a TTFB of 50ms, would it? – dpkdawg Jan 17 '19 at 17:12
  • @dpkdawg do you mind joining the litespeed slack channel ( https://golitespeed.slack.com/join/shared_invite/enQtMzE5ODgxMTUyNTgzLWVhZDNhZDNmYWRhZmIwNzUxN2Y2ZDRjZGUwZjFiMDk1ZTNjZDJmMDg5NTcyZjFiZDM4MDY1NjkwYjkzM2E5YmE ) - then ping me there, I'll see what I can figure out why it might not work for ya, so we find a solution and post it here :) – LucasRolff Jan 18 '19 at 18:40
  • @LucasRolff I actually figured out what was causing it, sort of. My server uses cPanel, and within cPanel I had activated compression under Optimize Website (mod_deflate). After turning this off the push worked as it should, showing Other / Push instead of just Other. Not sure why this was causing it yet. I noticed my site still has compression active (Brotli/GZIP), even after turning it off in cPanel. – dpkdawg Jan 29 '19 at 16:22