Tuesday, July 19, 2011

SPDY Server Push and CSS

‹prev | My Chain | next›

In the interest of slimming down my chain posts to focus on writing SPDY Book, I am going to try to solve just one problem today. And it may not even be a SPDY problem.

The problem is that my CSS is not being cached via SPDY server push. It seemingly gets pushed OK:
t=1311041561541 [st=  197]     SPDY_SESSION_PUSHED_SYN_STREAM  
--> associated_stream = 1
--> flags = 2
--> content-type: text/css
status: 200
url: https://localhost:3000/stylesheets/style.css
version: http/1.1
--> id = 2
But a little while later, a request for a second page asks for the stylesheet again:
t=1311041603258 [st=41914]     SPDY_SESSION_SYN_STREAM  
--> flags = 1
--> accept: text/css,*/*;q=0.1
accept-charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
accept-encoding: gzip,deflate,sdch
accept-language: en-US,en;q=0.8
host: localhost:3000
method: GET
referer: https://localhost:3000/one.html
scheme: https
url: /stylesheets/style.css
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.814.0 Safari/535.1
version: HTTP/1.1
--> id = 5
Interestingly, the referrer, /one.html, was not requested. It was SPDY server pushed into the browser's cache. And apparently stayed there.

Also odd is that the original CSS push did work—insofar as the original request did not make a secondary request for the CSS. Only upon a subsequent request did Chrome encounter a cache-miss.

So SPDY server push is working, but not for second requests of the CSS file. Weird.

Attempting to resolve this, I try just about everything I can think of. I push the CSS before the response. I push it after. I push before the HTML pages, I push it after. I add all sort of headers to the push, until...

I finally get it working when I add the "Last-Modified" header to CSS responses. I now have two exception in my SPDY server push code—one for pushing HTML (needs a content type) and a new one for CSS:
  if (/\.html?$/.test(url))
this._headers["content-type"] = "text/html";
if (/\.css$/.test(url))
this._headers["last-modified"] = "Wed, 20 Jul 2011 01:34:27 GMT";

I will most likely do away with the conditionals and simply always add the content-type and last-modified. Were this behavior to stick around, there might be some interesting games one could play with first page CSS and subsequent CSS. But that is hardly the kind of behavior that can be counted on (especially since this just happened in a recent dev release of Chrome).

As I was fiddling with cache, I noticed that SPDY server push resources do not seem to actually show up in about:cache. I try adding all necessary headers for caching:
  if (/\.html?$/.test(url))
this._headers["content-type"] = "text/html";
if (/\.css$/.test(url)) {
this._headers["cache-control"] = "public, max-age=3600";
this._headers["content-type"] = "text/css; charset=UTF-8";
this._headers["content-length"] = 111;
this._headers["etag"] = "111-1311125667000";
this._headers["last-modified"] = "Wed, 20 Jul 2011 01:34:27 GMT";

But it has no effect. The only cache entries for my local server are for the SSL cert that I am using and an accidental Google search:

Interesting. It seems that the SPDY cache is separate from the regular cache—at least in Chrome.

That is a fine stopping point for tonight. Up tomorrow: I start fiddling around with comparisons between SPDY and CDNs. That should be fun :)

Day #79

No comments:

Post a Comment