The Slow Way to SPDY

I’ve spent a few weeks casually investigating SPDY, and it’s now time to jot down some notes and take stock of how far I’ve managed to go (which is actually pretty far, considering I only started testing code yesterday).

In case you don’t know what SPDY is (and can’t be bothered to click on a link to find out), SPDY lets you have concurrent HTTP transactions inside a single TCP connection, turning it into a high-speed, secure protocol that aims to reduce page load times by 50%.

Although it’s been bouncing around for a while and is extensively used by Chrome to connect to Google servers (check out the net-internals screens if you’re running Chrome), it’s gone through a few iterations and has relatively few implementations - it’s now being integrated into the Mozilla Gecko codebase as a client library, but the only mass-market browser where you can take advantage of it now is Chrome, and the only popular sites running atop the protocol are Google’s (although some CDN firms like Strangeloop have already started folding SPDY into their service offerings).

One of the reasons I’m interested in SPDY is that I spent a considerable amount of time dealing with wanton optimization of HTTP traffic back in the WAP era, complete with on-the-fly compression and shoving multipart-related assets down a thin GPRS pipe to depressingly limited (but insanely optimized) browsers.

Another is that my site, given that it runs atop its own HTTP stack, allows me to do fancy tweaking of all sorts, and adding SPDY could be an interesting pastime.

However, getting hold of a stable SPDY implementation at this point is not unlike an uphill climb on a slow mudslide - the protocol is currently on its third draft but not really stable, most of the available code is outdated, and despite the links on this page, hardly any of it is easy to get to work in a weekend.

For instance, if you want to take the C route, you have to dig around in the Chromium source tree for a test server implementation that is tied to long and gnarly branches of their dependency tree, and whomever has an updated, clean server codebase isn’t saying so, even though there is an experimental Apache module and some discussion regarding other servers - but nothing you can pick up and run with straight away.

Furthermore, I’m running Varnish as a front-end, and the Varnish folk aren’t too keen on implementing SPDY until it’s widely acknowleged as the way forward (which hardly anyone wanted to until a few months ago, it seems).

So I’ve been looking for a way to either implement SPDY myself inside Yaki or setting up a simple reverse proxy that would talk to Varnish.

Fortunately, there is a partial Python implementation of the v2 draft that has seen some love and works with the current Chrome builds but (and herein lies another kink) only if you disable SSL support explicitly via the command line, which is a pain since it’s rather trivial to get the whole thing to work otherwise - you basically send out an Alternate-Protocol: PORTNUMBER:spdy/v2 header in your HTTP server, and you’re all set - the browser tries to switchover automatically.

Monkeying about with the code to use SSL/TLS on the proxy is easy enough, but it won’t work with “plain” TLS, because SPDY, being designed to coexist with HTTPS on port 443, uses a new TLS extension (in fact, a new negotiation method) called NPN (short for Next Protocol Negotiation) which is not implemented in most TLS libraries yet - it is in the latest OpenSSL, but it hasn’t trickled down to most distributions yet.

Google obviously has no trouble keeping their server stuff up to date with what they’re pushing out on the client, but on systems where you don’t really want to mess around with the stock TLS libraries, that’s a deal-breaker.

NPN is a relatively new affair so support isn’t easy to come by, but fortunately I’ve found a rather obscure patch for tlslite, a pure Python TLS library that I’ve been carrying around in my toolchest for ages (well, ever since I used it to debug some funky tunnels a couple of years back - it happens to be bundled with the Google GData API toolkit as well, so someone patched it to spec).

Based on previous experience (and considering that we now have a pretty good PyPy release), I’d say running a reverse proxy based on tlslite would be entirely feasible, so I went ahead, patched it up to the hilt and pinpointed the place to plug it in, but have had no time to actually do so yet (the changes themselves are straightforward, but the testing would likely take up another weekend’s worth of free time, and I’d rather finish reading Hyperion before getting back to work).

So I’m putting up the entire codebase at Github in case someone else wants to have a go, and focusing on other stuff in the meantime.