At Instart Logic we strive to make web applications more responsive with a software-defined architectural approach to application delivery. On one hand, we have client- and server-side technologies such as the Nanovisor and SmartVision, that enable our customers to deliver more responsive web applications; and on the other, optimizations on the TCP stack speed up the delivery of dynamic content.
While we are able to push latencies lower by optimizing at various levels of the application delivery stack, HTTP is a layer that does not lend itself easily to these optimizations. HTTP/1.1 tried to address some of these latency concerns by advocating connection reuse through keep-alive and pipelining of requests, but it still uses the same principle of serving serialized requests and responses. This means that if a request with a slow response is followed by more requests, they will all have to wait till the initial response is served – effectively increasing your page load times.
SPDY is a web protocol from Google that aims to solve these fundamental issues in HTTP. It does not replace HTTP, but modifies the way HTTP is transmitted over the network, with an aim to reduce the latency and to make the web more secure. Supporting SPDY is a natural thing for us to do at Instart Logic.
To make the deployment of SPDY as seamless as possible, SPDY uses a clever trick of layering on top of TLS (Transport Level Security). This basically ensures that most of the infrastructure components which typically handle SSL traffic without peeking into it will continue to work as-is. As web servers add support for SPDY, one could very easily assume that by just upgrading the application server, things will continue to work seamlessly. However, the reality is quite different.
In this blog post I’ll walk through some of the gotchas (if you will) that one needs to be aware of, if you’re considering supporting SPDY in your application.
End of HTTP Message
HTTP/1.1 relies on Content-Length or Transfer-Encoding to mark the end of body. With SPDY, a flag (FIN_FLAG) is set to indicate the end of body. Transfer-Encoding is no longer valid and Content-Length is advisory. The application server would handle this and give the application the valid body. However, it’s not uncommon for an application to look for the Content-Length header or the Transfer-Encoding header to determine if there is a body to the request or response. Such an application would end up ignoring the body if served over SPDY.
Handling of Duplicate Headers
Duplicate header names are not allowed in SPDY. If a header needs to have multiple values, they are sent as multiple NULL delimited values to the same key. Now this seems very innocuous since HTTP/1.1 says that multiple headers must be treated as the same header with a comma-separated value. That is,
Cache-Control: public Cache-Control: max-age=10
is the same as
Cache-Control: public, max-age=10
But there are plenty of real applications out there which don’t work this way. A very common example is multiple Content-Type headers (which is illegal by the specs but happens in real applications). Firefox “handles” this by accepting the last value of multiple Content-Type headers. A quick Google search shows that some HTTP clients accept the first value and some accept the last value. The bottom line is, in practice, two headers are not the same as one header with two values. One needs to be careful to ensure that the application makes no assumptions about this situation.
Header Name Case
SPDY has header names all in lowercase. This to me was amusing; I was reminded of the innumerable instances where we had to change the case of a header to “RFC case” since there are applications out there which look for a “Content-Type” (case insensitively) header and failed with a “content-type” header. We have encountered so many of these instances that we have made it a configurable option for customers. If your application is one of those that is picky about the case, it will likely miss some headers.
Compressed Request Headers
The request headers are compressed in SPDY. This basically implies that the user agent supports compression if it has sent a SPDY request. Which in turn implies that the server need not look at the Accept-Encoding header to send back a compressed body. Interestingly, google.com (at the time of this writing) sends uncompressed content to Firefox over SPDY, since Firefox drops the Accept-Encoding header! If your application is responsible for compressing responses based on the client sending the Accept-Encoding header, you must ensure that if it is being served over SPDY, you can assume that you have the Accept-Encoding: gzip header.
The Host Header
The URL portion of a SPDY request has a host:port – the consequence of which is the Host header is made redundant. Though an HTTP/1.1 application MUST support absolute URIs, most of the user agents send relative URIs and an application that expected a relative URI + a host header would have just worked fine. Such an application would now break when served over SPDY. This is so prevalent that the SPDY specs warn implementers to translate absolute URI to relative URI + Host header for an application.
There are more such nuances that you need to be aware of before you decide to support SPDY. In a perfect world – where your application and all the user agents are actually HTTP/1.1 compliant – there is probably not as much to worry about. But we all know that the web today is far from that ideal state, which makes SPDY support slightly trickier. Luckily for our customers, at Instart Logic we have spent time to ensure that the application behavior remains unchanged as we continue to deploy SPDY on our network, without customers having to worry about these nuances.
We have seen a definite improvement by enabling SPDY in our network, both in our internal monitoring metrics and also in our customers’ traffic, through a sharp decrease in page load times (the various tests we deployed and the ensuing results is potentially a topic for another blog post). SPDY does this by bringing about a rather drastic change in the way HTTP is delivered. At the same time it tries to make the migration to SPDY as transparent to the vast amount of infrastructure and applications out there, as possible. With more and more web servers supporting SPDY, many web application authors would hope that by upgrading their servers their application would automatically become more responsive. However, careful testing should be done to ensure you can walk SPDY before you can run SPDY!