dana-ross / http2-server-push

WordPress plugin that enables HTTP/2 server push for local JavaScript and CSS resources enqueued in the page.
MIT License
30 stars 5 forks source link

Don't do server push when referrer contains $__SERVER['SERVER_NAME'] #17

Closed roelven closed 6 years ago

roelven commented 7 years ago

We don't want to send all static assets on every page load and should save bandwidth when the browser already previously cached the assets. This could be detected by using a cookie, or checking if a referrer matches the current domain.

Since it's not guaranteed there is a cookie present and you probably don't want to introduce one, I'd suggest to go the referrer route.

dana-ross commented 7 years ago

The problem with that is it's not compatible with full-page caching. With a full-page cache like Batcache in place, if the first visitor to a page has the referer header set, nobody else will get assets pushed to them until the cache expires or is purged.

One workaround might be for your theme or plugin to use the http2_link_preload_src filter and check the Referer header. If your filter function returns an empty value (empty string, 0, null, false…) the plugin won't push any assets or include them in preload headers.

This code hasn't been tested, but I'm thinking it could be something like:

function roelven_only_push_on_first_visit( $src ) {

     // If the request contains a Referer header from this site (i.e. following an internal link)
     if ( isset( $_SERVER[ 'HTTP_REFERER' ] ) && false !== strpos( $_SERVER[ 'HTTP_REFERER' ], 'example.com' ) ) {
          return false;
     }

     // All else, return the original $src value
     return $src;
}
add_filter( 'http2_link_preload_src', 'roelven_only_push_on_first_visit' );

Batcache supports creating multiple cache "buckets" through vary_cache_on_function, but I'm hesitant to add support for specific cache plugins. Once I start down that road, I'm going to need to build and maintain support for the numerous cache plugins out there and it defeats the purpose of a simple plugin like this.

RavanH commented 7 years ago

Isn't it up to the browser to accept the server push or not? If it has a file in cache it's not obligated to "preload" that file again...

If a browser does not cache pushed resources, than that's a browser issue.

dana-ross commented 7 years ago

Yes and no. The way server push works is the server sends its intent to push a file and then just goes ahead and starts sending it at some point after. The browser can send a cancel signal for that data stream and the server should stop sending it.

I've seen this behavior when debugging server push in Chrome. But my understanding is not every browser will cancel the stream like that. And even the browser does, there's a chance a couple packets of the file were sent already by the time the cancel is processed.

So I get why this is so important to people. I just don't have a good way to do it within the framework WordPress gives us.

RavanH commented 7 years ago

...not every browser will cancel the stream like that.

Like I said, a browser issue ;)

I'd say the discussion about overhead of sent packets (before a push is cancelled) on second visits being worth it against the speed benefits of server push on first visit, is outside the scope of this plugin. As is creating a fix/work-around that fits all scenarios... In fact, might it not negate the speed benefits when too much stuff like this is handled on PHP level?

dana-ross commented 6 years ago

Browsers and server makers are messing around with "cache digests" but they also have an inherent privacy risk. I'm waiting to see if the proposed IETF standard to build cache digests into the protocol itself goes anywhere.