How HTTP/2 Pushes the Web
push.netray.io
push.netray.io
I think we will definitely get there in the near future. I also think that one can definitely get a well-crafted application together by hand, but until the tooling catches up, it will not be widely used.
One thing that could be done is a webserver that tracks which resources are most commonly requested within say 5 seconds of an initial resource, and if >N% of them also request a given resource, it gets pushed by default. That could be a good starting point, but then comes the cost of keeping those relations/counts/tables in memory and not overloaded.
Definitely some opportunities out there.
A few years ago I heard the argument that it basically benefits Google and other large companies and inconveniences everyone else.
Downsides:
* TLS requirements are complicated and hardly anyone knows how it works.
* Several agents partially support it, but the overlapping feature set is useless. An easy example is trailers.
* More complex implementation. You can't look at the bytes without a program to decode the frames.
* Flow control is hard.
Upsides:
* Too numerous to count.
HTTP/2 fixes all the most painful parts of HTTP/1.1, and even provides backwards compatibility for HTTP/1.1 proxies. Aside from bugs (and lack of counterparty support), there is no reason to keep using HTTP/1.1.
* TLS requires ALPN. This would not be so bad, but so many clients don't provide a way to set the ALPN string. Java. In old versions of Java there is no way to do so, except to hack the JDK classpath. (Go users are feeling pretty smug right about about now, but the rest of the world suffers).
* Setting up more advanced TLS is highly undocumented. Anything such as custom host domain validation, or IP SNI, or client side certificates, or encrypted keys results in people getting stuck. There is very little help available (how would you do this in nodejs, or ruby, or python, or C#, or PHP, etc.?)
* Modern ciphersuites are not supported everywhere. For a long time, Java8 had non-hardware acceleration of AES-GCM, at a max speed of about 20MB/s per core. (on Intel, the max speed it closer to 3500MB/s). This makes it prohibitively expensive on languages/libraries that don't support it. (I'm looking at you, Android.)
* How do you test TLS? LetsEncrypt rate limits cert creation. For the purpose of CI, there isn't an easy way to get trust on both sides. Unit test become a pain, so people just don't encrypt.
With this point, I just wanted to say, I have to agree fully. The requirements that get forced on folks just to adopt HTTP/2 are frustrating. As much as I also like PFS, tying HTTP/2 to it was silly, IMO. If the old ciphers are really that bad, I wish the vendors would just commit to that and put out a timeline for deprecating them. But this "they're only bad if you're using HTTP/2" to me seems like a nonsense carrot and stick.
> client side certificates, or encrypted keys
These aren't particular to HTTP/2 though; you can use or not use them equally the same w/ HTTP/1.x. (In particular, client certs aren't going to effect most people.)
> How do you test TLS? LetsEncrypt rate limits cert creation. For the purpose of CI, there isn't an easy way to get trust on both sides. Unit test become a pain, so people just don't encrypt.
Testing your certificate issuance stuff is orthogonal to HTTP/2, again, is it not? Outside of ensuring you get the appropriate key usage bits set on the certificate, I don't see why it shouldn't be very feasible, for testing HTTP/2, to simply mock out LE w/ a self-signed certificate.
> TLS requires ALPN.
Supported by recent versions of Ruby pretty well, but as you say, older versions, not so well.
> Setting up more advanced TLS is highly undocumented.
It was slightly tricky with Ruby but it provides the appropriate callbacks and the documentation is reasonable: https://github.com/socketry/falcon/blob/940c25f4d19e9ad900ce...
> How do you test TLS?
I specifically solved this problem by using a self-signed local certificates and certificates store: https://github.com/socketry/async-rspec/blob/master/lib/asyn...
That code makes appropriate contexts available for client and server in unit testing.
Additionally I hacked this together: https://github.com/socketry/localhost
It generates local self-signed certificates which you can easily use with a web browser. It solves the "localhost development via https" problem.
HTTP/2 in my opinion is simply a better protocol. It's more robust, and it has a binary framing layer which implements connection semantics separately from request/response headers. What I mean by this, is `content-length` or `transfer-encoding` are no longer used to control how the protocol actually works (i.e. how many bytes of data are consumed). I think this is a great step forward because it removes ambiguity and simplifies the overall protocol, and it's clear how extra features can be added in the future without impacting existing clients/servers - something that HTTP/1 struggled with a bit.
I also think it impacts how we build web applications. I already wrote this as a blog post: https://www.codeotaku.com/journal/2018-10/http-2-for-ruby-we...
Do you expect someone to go into every language and look for what framework names they have?
There's also a PHP framework named "Phalcon" which is pretty damn close to "Falcon" -- should they be bashed too?
I think it might be helpful to have a setting that disables server push for those devices. However the problem here is that most users will neither discover nor understand the setting. Maybe if the ISPs would signal the phone firmware something about the data plan, and that one could switch the push setting it could help, but that's unlikely to happen.
Another remedy could be that push implementations on the server only push the headers and don't begin streaming the body, so that the client can check (e.g. through cache and etag comparisons) whether it really wants it. But that's some kind of departure from generic HTTP/2: The client can't really send that it wants the remaining body, since the only signal that it has is the flow control window increment. Clients would need to get modified to send this always when receiving push promises, and servers would need to understand that those should now trigger them to start streaming bodies. If not all do it then it seems like a recipe for stuck requests, and a nightmare for interoperability. So that's also unlikely to happen.