Deploying SPDY: 5 gotchas to consider
Optimising HTTP can be tricky. And that’s where SPDY comes in. Designed to reduce latency and increase security, Google’s web protocol can nicely fill the holes of HTTP.
When delivering highly responsive web applications, developers must optimise the application delivery stack. However, HTTP is a protocol that currently does not easily lend itself to optimisation.
While the impending release of HTTP/2 may solve some of these shortcomings, developers need to best leverage the tools they have today to improve latency. A web protocol from Google called SPDY aims to solve these fundamental issues in HTTP and does so by modifying the way it is transmitted over the network, effectively reducing latency and increasing security. And since SPDY is very closely related to HTTP/2 it provides a good indicator of what’s to come.
To make SPDY deployments seamless, it uses a clever trick and layers on top of TLS (Transport Level Security). Essentially, this 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, it’s often assumed that simply upgrading the application server will enable processes to continue to work with ease. However, the reality is that the process is not always as seamless as expected. As developers set out to upgrade the application server they need to be aware of these five SPDY gotchas:
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, then 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 that 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. To me, this was amusing and reminded me 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.
These instances are so common that it’s best to make it a configurable option. If your application is picky about the case, it will likely miss some headers.
Compressed Request Headers
Request headers are compressed in SPDY. This implies that the user agent supports compression if it sent a SPDY request and that the server doesn’t need to 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’s served over SPDY you have the Accept-Encoding: gzip header.
The Host Header
The URL portion of a SPDY request has a host:port, and by consequence the Host header is redundant. Though an HTTP/1.1 application must support absolute URIs, most 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 SPDY specs warn implementers to translate absolute URI to relative URI + Host header for an application.
There’s no doubt that SPDY drastically changes how HTTP is delivered resulting in substantial improvements such as decreased page load times. For these reasons, more and more web servers are supporting SPDY with the hope that applications will automatically become more responsive. In a perfect world your applications and user agents would be HTTP/1.1 compliant so application behavior could remain unchanged during SPDY deployment. However, the web is far from an ideal state making SPDY support tricky.
To successfully deploy SPDY in today’s world, developers must be aware of these key nuances mentioned above and conduct careful testing. After all, it’s best to walk before you run with SPDY.