Category Archives: Development Frameworks

Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It?

It’s well known that Internet Explorer aggressively caches ajax calls whereas all the other browsers grab the data fresh every time. This is usually bad: I’ve never encountered a case where I want ajax to NOT contact the server. Firefox, Safari and the other browsers know this and don’t cache ajax calls.  It’s not illegal or anything, it’s just caching to the maximum extent permitted by the spec.

In IE9’s new F12 Developer Console (finally!), cached requests show up as 304 Not Modified with a very suspicious < 1 ms response time.  The 304 is a red herring:  the server is never contacted.  It simply means IE in its infinite wisdom has decided the response wouldn’t have been modified IF it had asked the server, and serves it from browser cache.  Debugging on the server side shows that IE is really and truly *not* hitting the server.

This is a problem on all versions of IE:   IE9, IE8, IE7, and IE6.  People were scratching their heads over it way back in 2006.

To prevent Internet Explorer from caching, you have several options:

  • Add a cache busting token to the query string, like ?date=[timestamp].  In jQuery and YUI you can tell them to do this automatically.
  • Use POST instead of a GET
  • Send a HTTP response header that specifically forbids browsers to cache it

Of these, the HTTP response header is what I consider the “correct” solution.  But I’ll go through all of them below.

Cache Buster in Query String

On every ajax request, you can add a cache busting token to the query string, like ?date=[timestamp]

If you are using JQuery or YUI (the two frameworks I use the most), you can tell THEM to add the cache-busting parameter.

JQuery even has a global parameter to disable caching — set it in your <head> (like in your site template), and you’ve just cache-busted any ajax call jQuery makes.

However, I don’t like this approach:

  • It sends unnecessary data to the server that may interfere with the request.  Like, maybe the request takes an arbitrary number of parameters and the cache busting parameter becomes one of them.
  • Also, it clutters up the browser’s cache with a bunch of content that it’ll never serve, leaving less space for the content that SHOULD be cached.

POST Instead of GET

You can send your ajax call as a POST instead of a GET.  Browsers will never cache a POST.

However, I don’t like this approach either:

  • POSTs are for calls that modify the server.  If you are retrieving information from the server without modifying anything, you should stick with a GET.
  • I’ve also heard that POSTs are slower in ajax than GETs, but that’s a very minor secondary consideration.

Set Cache Headers Correctly

This is what I’d call the “correct” approach:  when the server sends an ajax response, have it set a HTTP header that tells all browsers to NOT cache your content because, well, you don’t WANT it to be cached.

You should, anyway:  Firefox and Safari just happen to be making a convenient assumption that you don’t want your ajax calls cached, whereas IE caches as much as it can get away with.  This will make all browsers’ behavior consistent.

How to do this?  Well, setting the caching in every single one of your server calls is for the birds.  You want something that applies to all ajax calls globally.   Fortunately, most javascript libraries — including jQuery, YUI, Mootools and Prototype — send a X-Requested-With: XmlHttpRequest header on every ajax request.

In the Java world, you can write a response filter that detects the X-Requested-With: XmlHttpRequest header and sets a “don’t cache this” header.

But in the Groovy world of Grails, there’s something even easier (of course). Below is a Grails filter that prevents caching of ajax requests that identify themselves with the X-Requested-With: XmlHttpRequest:

// put this class in grails-app/config/
class AjaxFilters {
    def filters = {
        all(controller:'*', action:'*') {
            before = {
                if (request.getHeader('X-Requested-With')?.equals('XMLHttpRequest')) {
                    response.setHeader('Expires', '-1')
                }
            }
        }
    }
}

Some people prefer to use the Cache-Control: no-cache header instead of expires. Here’s the difference:

  • Cache-Control: no-cache – absolutely NO caching
  • Expires: -1 – the browser “usually” contacts the Web server for updates to that page via a conditional If-Modified-Since request. However, the page remains in the disk cache and is used in appropriate situations without contacting the remote Web server, such as when the BACK and FORWARD buttons are used to access the navigation history or when the browser is in offline mode.

By adding this filter, you make Internet Explorer’s caching consistent with what Firefox and Safari already do.

Installing Groovy on OS X 10.6

Groovy is an agile, dynamic language for the Java platform. It has the speed and flexibility of Ruby but it compiles down to Java bytecode. It’s the foundation of the Grails framework.

Here’s how to install Groovy 1.7.9 on Mac OS X 10.6 Snow Leopard.  It should also work on earlier versions of Groovy and OS X. I will note that Groovy does provide instructions, but I prefer these. There’s also a MacPorts installer, but I never have any luck with MacPorts.

Install Java SDK

Before you install Groovy, make sure you have a Java SDK 1.5+ installed.  The Java runtime that comes preinstalled with OS X does not have the SDK.

Download Groovy

Download Groovy from groovy.codehaus.org.

Install Groovy

Unpack the archive you downloaded.  It’ll be a folder.

Move the folder to /usr/share/java. I just used Finder, but here’s the obligatory Terminal command:

$ sudo mv ~/downloads/groovy-1.7.9/usr/share/java

Create a symlink that allows you to access Groovy without referencing the version number.  This way, to upgrade your Groovy you just install the newer version alongside the old one, and update this symlink.  This is a standard best practice.

$sudo ln -s groovy-1.7.9 groovy

To make Groovy available, add the following either to /etc/profile (for everyone) or ~/.profile (for just you):

export GROOVY_HOME=/usr/share/java/groovy
export PATH=$GROOVY_HOME/bin:$PATH

If you haven’t set the JAVA_HOME environment variable yet, create one in .profile that points to the path where Java’s installed. It’ll be something like this.

export JAVA_HOME=/Library/Java/Home

Let’s see if it works. Open Terminal and type:

$groovy

You should see:

Groovy Shell (1.7.9, JVM: 1.6.0_24)
Type 'help' or '\h' for help.
------------------------------------------------------------
groovy:000>

This is Groovy’s interactive command shell. Hit Ctrl-C to exit.

Now go get yer Groov on!

Installing Grails on OS X 10.6

Grails is an excellent rapid application development framework that integrates well with many industrial-strength analytics products.

Here’s how to install Grails 1.3.7 on Mac OS X 10.6 Snow Leopard.  It should also work on earlier versions of Grails and OS X. I will note that Grails.org does provide instructions, but I prefer these.

Install Java SDK

Before you install Grails, make sure you have a Java SDK 1.5+ installed.  The Java runtime that comes preinstalled with OS X does not have the SDK.

Download Grails

Download Grails from grails.org.

Install Grails

Unpack the archive you downloaded.  It’ll be a folder.

Move the folder to /usr/share/java. I just used Finder, but here’s the obligatory Terminal command:

$ sudo mv ~/downloads/grails-1.3.7/usr/share/java

Note:  some people install it to /usr/share/, but these instructions install it to /usr/share/java because that’s where other Java tools like Maven, Ant, JUnit and Derby are installed. Grails’ official instructions suggest your home directory (~/grails), which is just plain weird.

Change ownership and permissions:

$cd /usr/share/java
$sudo chown -R root:wheel grails-1.3.7/
$sudo chmod 0755 grails-1.3.7/bin/*

Create a symlink that allows you to access Grails without referencing the version number.  This way, to upgrade your Grails you just install the newer version alongside the old one, and update this symlink.  This is a standard best practice.

$sudo ln -s grails-1.3.7 grails

To make Grails available, add the following either to /etc/profile (for everyone) or ~/.profile (for just you):

export GRAILS_HOME=/usr/share/java/grails
export PATH=$GRAILS_HOME/bin:$PATH

If you haven’t set the JAVA_HOME environment variable yet, create one in .profile that points to the path where you have installed Java. It’ll be something like this.

export JAVA_HOME=/Library/Java/Home

Let’s see if it works. Open Terminal and type:

$grails

You should see:

Welcome to Grails 1.3.7 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /usr/share/java/grails
No script name specified. Use 'grails help' for more info or 'grails interactive' to enter interactive mode

Happy Grailing!