It's simply a matter of adding appropriate Link headers to responses and we can push stuff to clients. This makes it easy to run experiments without having to have a server that already supports push.
We rolled this out precisely so people can experiment and we are very interested to understand how people are using it and what performance improvements and problems they run into.
The day CloudFlare forces me to run a blog post by the PR and Legal team for approval because of worry that I might offend someone will be a pitifully sad day. That would be ridiculous.
No, I'm not. But, it might take on a different meaning to other people. Most blog posts are run by the PR and Legal team and big companies because they could be a liability to the corporate image.
I reduced Server Push to these rules for my HTML pages:
* Push only when I can guarantee that they don't have it in cache
* Push only assets included in the <head>
Which, for me, means I push a single CSS file for a page when I know that the visitor is a new visitor. After that, I never push again.
The implementation is essentially:
* For a HTML page request
* Check for the existence of a pushed=true cookie
* If cookie does not exist (new user/session) push the CSS needed
* And add a Set-Cookie for pushed=true with the same cache expiry time as the CSS resource
That's it.
Of course... if we could move away from sending the CSS for a whole site when people just request a page then I'd revisit this, but until then a single CSS file needs a single cookie and a single push.
I am a bit surprised that client side caching seems to be an afterthought of http2. It was the first thing that jumped to my mind the day I first heard of http2 push.
And this caching can become a privacy issue. The client producing a list of what it has in cache can become a new form of cookie. The cache would have to be cleared at the end of each session to mitigate this risk.
Caching is already a privacy issue with etags. HTTP2 doesn't make that situation worse. Besides the web has become so complex and offers so much for fingerprinting, that this battle has been lost long ago.
In order to have actual privacy you'd need to redesign the web from the ground up and consider privacy implications at every step. Even then you might come to the conclusion that it's just not possible to guarantee privacy.
> And this caching can become a privacy issue. The client producing a list of what it has in cache can become a new form of cookie. The cache would have to be cleared at the end of each session to mitigate this risk.
Is this really a significant privacy issue? Server can deduce which items (I use word "item" to refer to a resource cache entry) are missing from client cache just by monitoring follow-up requests by the client. Of course this way server can't know anything about the items client has but are not present on the page.
Maybe some cryptography can be used here, so that client can tell the server items it has, but in such a way that server can't know anything more than what it strictly needs.
Client could for example hash each item signature with salt and send this information to the server, salt + a list of hashed items. This would prevent direct lookups, but of course the server could still compute same value (hash of signature + salt) for all items in a database.
Maybe it's somehow possible to have even stronger privacy guarantees while still allowing server to compute which items have a high probability to be needed by the client based on some information client included in the request?
Another idea: client could send a bloom filter [1] of the related items it already has plus random hashing data to compute it. Server would use client provided hashing parameters to compute bloom filter bit index for each item and push it if the bit wasn't set. Of course this would sometimes cause server not to push needed data. Frequency when this happens would depend on the bloom filter size the client chooses versus number of potential items.
Because the client chooses bloom filter hashing parameters, this would mask the set of items the client possesses. This makes the data about already cached items almost useless for fingerprinting purposes, while still keeping some of the server push performance gain. Client can pick the tradeoff between performance and privacy with bloom filter size.
> Is this really a significant privacy issue? Server can deduce which items (I use word "item" to refer to a resource cache entry) are missing from client cache just by monitoring follow-up requests by the client.
Conceivably, a server could generate random null resources which are cached by the client and can then be used, as the GP indicates, to identify it — yet another supercookie.
It sounds interesting, but I suspect that you're right that caching leaks no matter what — I wonder if it's almost like compression in that sense (and we remember how compression impacts HTTPS!).
I have very fast mobile internet (4G, so I can download megabytes of traffic in one second) yet this traffic might cost a lot. And my pings to US server might easily be second or more. So basically I risk to download an entire website which is already in the my cache for each HTTP request.
Honestly I'm not sure that I like this server push. I think, the only appropriate use is: server push if client misses some cookie and set this cookie immediately.
We're working on a draft that will allow clients to signal what resources are already in their cache. This should allow us to reduce the bandwidth risk of unnecessary pushes.
Wanted to note that iOS 10 will support HTTP/2 push for apps too. iOS will internally cache the pushed content and requests for them will appear to respond instantly.
I wrote about using a bloom filter and HTTP2 push for loading modules (instead of bundling them), and implemented a PoC using service workers: https://mariusgundersen.net/module-pusher/
I appreciate in-depth analysis, the numbers, and the actual case studies, and resulting recommendations. This is a very good resource that puts actual numbers to the issue.
In my opinion, this reveals that HTTP/2 Server Push is essentially one huge microoptimization, proper use of which requires even more effort from both the server (and the client):
[1] watch and aggressively respond to network utilization
[2] construct a dependency graph of resources (presumably by actually parsing the HTML on server-side, or beforehand out-of-band and store it some other place)
[3] have the client communicate the state of its cache! [ref-1]
Anyone have a good HTTP/2 web server that supports Push as well as WSGI?
NGINX doesn't support push it seems, and looking around for an HTTP/2 server that does support push, the only one I found was h2o (https://h2o.examp1e.net) but that doesn't support WSGI, for dynamic python apps.
27 comments
[ 4.8 ms ] story [ 69.1 ms ] threadIt's simply a matter of adding appropriate Link headers to responses and we can push stuff to clients. This makes it easy to run experiments without having to have a server that already supports push.
https://blog.cloudflare.com/http-2-server-push-with-multiple...
We rolled this out precisely so people can experiment and we are very interested to understand how people are using it and what performance improvements and problems they run into.
Which image are you talking about? Is it https://commons.wikimedia.org/wiki/File:They_started_our_car... which depicts people help restart a car by pushing it?
* Push only when I can guarantee that they don't have it in cache
* Push only assets included in the <head>
Which, for me, means I push a single CSS file for a page when I know that the visitor is a new visitor. After that, I never push again.
The implementation is essentially:
* For a HTML page request
* Check for the existence of a pushed=true cookie
* If cookie does not exist (new user/session) push the CSS needed
* And add a Set-Cookie for pushed=true with the same cache expiry time as the CSS resource
That's it.
Of course... if we could move away from sending the CSS for a whole site when people just request a page then I'd revisit this, but until then a single CSS file needs a single cookie and a single push.
And this caching can become a privacy issue. The client producing a list of what it has in cache can become a new form of cookie. The cache would have to be cleared at the end of each session to mitigate this risk.
I am shocked — shocked! — that Google would develop a standard with built-in privacy attacks.
In order to have actual privacy you'd need to redesign the web from the ground up and consider privacy implications at every step. Even then you might come to the conclusion that it's just not possible to guarantee privacy.
Is this really a significant privacy issue? Server can deduce which items (I use word "item" to refer to a resource cache entry) are missing from client cache just by monitoring follow-up requests by the client. Of course this way server can't know anything about the items client has but are not present on the page.
Maybe some cryptography can be used here, so that client can tell the server items it has, but in such a way that server can't know anything more than what it strictly needs.
Client could for example hash each item signature with salt and send this information to the server, salt + a list of hashed items. This would prevent direct lookups, but of course the server could still compute same value (hash of signature + salt) for all items in a database.
Maybe it's somehow possible to have even stronger privacy guarantees while still allowing server to compute which items have a high probability to be needed by the client based on some information client included in the request?
Another idea: client could send a bloom filter [1] of the related items it already has plus random hashing data to compute it. Server would use client provided hashing parameters to compute bloom filter bit index for each item and push it if the bit wasn't set. Of course this would sometimes cause server not to push needed data. Frequency when this happens would depend on the bloom filter size the client chooses versus number of potential items.
Because the client chooses bloom filter hashing parameters, this would mask the set of items the client possesses. This makes the data about already cached items almost useless for fingerprinting purposes, while still keeping some of the server push performance gain. Client can pick the tradeoff between performance and privacy with bloom filter size.
[1]: https://en.wikipedia.org/wiki/Bloom_filter
Conceivably, a server could generate random null resources which are cached by the client and can then be used, as the GP indicates, to identify it — yet another supercookie.
What do you think about my bloom filter idea?
It sounds interesting, but I suspect that you're right that caching leaks no matter what — I wonder if it's almost like compression in that sense (and we remember how compression impacts HTTPS!).
Honestly I'm not sure that I like this server push. I think, the only appropriate use is: server push if client misses some cookie and set this cookie immediately.
More details in the NSURLSession WWDC talk: https://developer.apple.com/videos/play/wwdc2016/711/
In my opinion, this reveals that HTTP/2 Server Push is essentially one huge microoptimization, proper use of which requires even more effort from both the server (and the client):
[1] watch and aggressively respond to network utilization
[2] construct a dependency graph of resources (presumably by actually parsing the HTML on server-side, or beforehand out-of-band and store it some other place)
[3] have the client communicate the state of its cache! [ref-1]
[4] have custom, conditional logic for cookies
----
[ref-1] https://tools.ietf.org/html/draft-ietf-httpbis-cache-digest-...
NGINX doesn't support push it seems, and looking around for an HTTP/2 server that does support push, the only one I found was h2o (https://h2o.examp1e.net) but that doesn't support WSGI, for dynamic python apps.