jesse's weblog

Tuesday Oct 21, 2008

Safari Caching and Embedding Jetty

I ran across a curious issue with safari recently related to caching. I opened it as an issue with Apple because I think its a nasty little issue, and I added it to the jetty wiki recently but I figured it was a big enough gotcha that I would toss a blurp about it here in the hopes of helping someone running across the issue in the future.

There are a host of good descriptions of how various browsers cache their static content and determine whether or not they need to check for updates for it. The best known and most used is probably the Last-Modified: header coupled with something like Expires: to force content to be either reloaded all the time or not at all by putting it far enough into the future. What was recently noticed was that with Safari (at least version 3.1.2 (5525.20.1)) the Last-Modified: header was not enough to achieve even minimal caching. With Firefox simply returning the Last-Modified: header would cache static content for a while but not so with Safari _if_ the Date: header was missing. So...the Date: header appears to be a required header for Safari to use the Last-Modified: header for basic static content caching.

Now what does this have to do with embedding jetty?

Well jetty is really easy to embed, a few lines and you have a full fledged http server in your application, ready to serve content to your hearts desire. If you start up jetty through the normal distributions you are covered because by default the 'sendDateHeader' value is set to true (check the bottom of your jetty.xml). However when embedding jetty, by default it doesn't send the Date: header, it is an option that you need to set through the api.

Server jettyServer = new Server( 8080 );
jettyServer.setSendDateHeader( true );

Now your served pages will pass back the Date: header and safari can go about whatever caching mechanism it is using without constantly checking if static content you have served has changed. So if your embedding jetty and safari is one of your targeted platforms then it is worth double checking that your sending the Date: header back with your responses. Its a pretty simple thing to do that can cut a lot of superfluous calls from safari browsers if its happening for you.

I can't emphasize enough the usefulness of applications like wireshark or charles in debugging odd browser/server situations like this, but that is another story.

Comments:

RFC 2616 says that “Origin servers MUST include a Date header field in all responses” unless they have no clock, and the JVM always has System.currentTimeMillis(), so shouldn’t Jetty default to sending the Date header anyway?

Safari is only required to generate its own date for the response if it wants to cache it. I guess they’ve turned this around, decided to not generate their own dates, and therefore to not cache Date-less responses.

Posted by Carey on October 21, 2008 at 08:53 PM CDT #

I guess they’ve turned this around, decided to not generate their own dates, and therefore to not cache Date-less responses

Posted by Bobby on December 16, 2008 at 06:09 PM CST #

Post a Comment:
  • HTML Syntax: Allowed

Webtide

Calendar

Tags

Search

Links

Navigation