• Home
  • Blog
  • Wiki
  • Projects
  • Contact Us






Using Time Stamp Parameters to Avoid Stale Responses To Redirected Requests

July 12th, 2009 By admin

I recently ran into an annoying bug caused by Internet Explorer caching the content of redirected requests.  My fix involved adding a time stamp valued parameter on to the  URL returned with the 302 (redirect) status code.   The new parameter serves to ensure that the URL to which the client is being redirected is unique by virtue of the ‘cache busting’ time stamp. Since the URL will never have been seen before,  the browser will not attempt to use a cached copy.  The only caveat here is that if your server clock is ever reset, there is an astronomically small chance that a millisecond value previously sent to a given browser might be reused. In this very rare case the browser will not attempt a fetch in response to the redirect directive because it will mistakenly believe that it already has a copy of  the content associated with the (previously seen) URL.

I was initially going to solve the problem by jamming in cache control headers,  but I find these tricky to get right (although after reading this article I’m pretty sure that specifying max-age=0 is the thing to do, although no-store seems like it would serve as well.)  In any case, for now, I’m sticking with my cache busting parameter approach. It seems very straight forward and virtually (modulo the caveats above) foolproof.

Reproducing the Incorrect Behavior

I’ve attached a code sample to illustrate how this technique can be used in a simple controller.  To reproduce the “caching-of-redirected-requests” bug you must use Internet Explorer. Since FireFox works fine I’m guessing that one of these browsers is not performing to specification, but I’m not sure which one.  In any case, my task was to support IE, so my fix ensures corrects behavior on this browser platform (as well as FireFox, and presumably others as well.) To get started, download the attached grails project zip archive,  change to the ‘books’ directory, then  run the application via the command:

grails run-app

Don’t change the port from 8080 because the example hard codes that. From IE, type the URL:

http://localhost:8080/books/book/getViaRedirect?doRedirect=true&addToResponse=haha

You will see the message  ‘addition is haha’ written to standard out. This logs the fact that the content of the file /results.html is being appended to (with whatever value you specify via addToResponse).

Your browser will show the string:

content that will be sent as response to a redirected request haha

If you continue to type
http://localhost:8080/books/book/getViaRedirect?doRedirect=true&addToResponse=haha

you will see the same message being printed to standard out as the contents of results.html gains more and more lines of  ‘haha’. But the response rendered in the browser will not change (because IE is  using the cached value of http://localhost:8080/books/results.html.)

Now, if you repeat this same test wtih Firefox you will see the length  of the response content grow with each request, like this:

content that will be sent as response to a redirected request haha

content that will be sent as response to a redirected request haha haha

content that will be sent as response to a redirected request haha haha haha


This is because you are seeing the most recently updated contents of the  file that backs http://localhost:8080/books/results.html.


Code Walk-Through

The getViaRedirect action of BookController is fully reproduced below.

1    def getViaRedirect = {
2      if (params.doRedirect == "true") {
3        String fileSystemPath =
4            servletContext.getRealPath("/result.html")
5        println "fileSystemPath is $fileSystemPath"
6
7        File responseFile = new File(fileSystemPath)
8
9        String addition = ""
10        if (params.addToResponse) {
11          addition += "\n" + params.addToResponse
12          println "addition is $addition"
13        }
14
15        responseFile.text += addition
16
17        if (System.properties("cacheBust") == "true"){
18          redirect(url: "http://localhost:8080/books/result.html",
19                   params: [cacheBuster: new Date().getTime()]
20          )
21        } else {
22          redirect(url: "http://localhost:8080/books/result.html")
23        }
24      }
25      else {
26        render("no redirecting. Here is some static text.")
27      }
28    }

On lines 3 and 4 we get the actual file system path of the /results.html resource and we (conditionally) append the string value of the ‘addToResponse’ parameter to the end of that file.  On lines 17 through 22 we redirect the browser to requery for /results.html. The test at line 17 ensures that if you start grails with the -DcacheBust=true option, then the URL will be augmented with the cache busting parameter.

To try out the fix all you need to do is restart Grails via the command:

grails   -DcacheBust=true run-app

Then try to reproduce the incorrect behavior with IE using the steps given above.  This time you will see the correctly updated contents of the /results.html file.

Have fun !

grailscodesample_redirect1

Share:
  • Digg
  • del.icio.us
  • Facebook
  • Mixx
  • Google
  • blogmarks
  • description
  • Furl
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • Netvouz
  • NewsVine
  • Ping.fm
  • Pownce
  • Reddit
  • StumbleUpon
  • Technorati
  • Tumblr
  • TwitThis
  • Yahoo! Buzz
  • YahooMyWeb

Posted in Grails, Groovy | 1 Comment »




One Response to “Using Time Stamp Parameters to Avoid Stale Responses To Redirected Requests”

  1. By Using Class Level Metadata to Allow Controller Actions to Opt Out of a Filter’s Processing | Build Lackey Blog
    on January 5th, 2010

    [...] is designed to solve the Stale Responses To Redirected Requests problem that I wrote about in a prior post. Basically, the problem has to do with a bug in IE that makes your Ajax requests seem to do nothing [...]


Leave a Reply

  • Categories

    • Build Automation
      • Maven
    • Development Environment Tricks
      • Cygwin
    • Dynamic Languages
      • Groovy
        • Grails
    • Java
    • JQuery
    • Test Automation
      • Selenium
    • Uncategorized

  • Archives

    • June 2010
    • March 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • September 2009
    • July 2009
    • June 2009
    • May 2009
    • April 2009
    • March 2009
  • Meta

    • Log in
    • RSS
    • Comments RSS
    • Valid XHTML
    • XFN
    • WP