views:

538

answers:

2

I have got a familiar problem. I am using Django-0.97, and cannot upgrade -- though the version of Django being used should not play any part in the cause of the problem.

I have a search view that presents a form to the user, and, on submission of the form via POST, performs heavy computations and displays a list of items that are generated as a result of those computations. Users may click on the "more info" link of any of those items to view the item detail page.

Users on IE, once they are on the item detail page for any item from the search results page, get the familiar "webpage has expired, click on refresh button, yadda yadda yadda" error when they hit the "back" button on the browser. Sadly, a good majority of the users of the site use IE, are not tech savvy, and are complaining about this problem.

Thinking that setting up a cache backend may solve the problem, I configured a simple cache backend. I juggled with per-site cache and per-view cache, but to no avail. And now, I am not too sure I have set up the cache stuff properly.

Any hints, suggestions that may help in mitigating the problem will be hugely appreciated.

Thanks.

UPDATE (20 July 2009)

I have used Fiddler to inspect the HTTP headers of both the request and response. IE is sending the Pragma: no-cache header in the POST request. The HTTP response generated as a result of the request has the following headers:

Cache-Control: public, max-age=3600
Date: someDateHere
Vary: Cookie

And, yes, I am not using the PRG pattern.

+2  A: 

Under RFC2616, "POST" is not an idempotent method, which means that the browser will not resend the request unless the user confirms that resend. So, to prevent the prompt, you must ensure that the CLIENT caches the page.

To do so, use the Cache Control header: http://www.fiddler2.com/redir/?id=httpperf and ensure that you are not sending back any Vary or Pragma: no-cache headers: http://blogs.msdn.com/ieinternals/archive/2009/06/17/9769915.aspx

It would be helpful for you to capture your HTTP POST's response headers (e.g. with Fiddler) and update your question with them.

EricLaw -MSFT-
Thank you for your response, EricLaw. I have updated the question. Do you think the "Vary: Cookie" may be the source of the problem?
ayaz
Yes, a Vary: Cookie will absolutely cause IE to treat the page as non-cacheable.You can verify this is the problem easily by simply using Fiddler to remove the Vary header and see if it starts working.
EricLaw -MSFT-
Thanks, again, EricLaw. I went with the PRG pattern, as I explain in the comments under the selected answer. That has worked for me. Fiddler is a nice application. I found it pretty useful. Thanks.
ayaz
+1  A: 

You may find you need to use the PRG pattern (Post/Redirect/Get). With this pattern, the handler for the POST will:

  1. perform the heavy computations, determine the search results, and store them in the user's session (or store them in the db keyed by the user's session).
  2. Send a response with a redirect header to an idempotent page, which is then fetched by the browser using a GET, when it follows the redirection.

When the redirected-to page is accessed, the server displays the search results page, computed from the stored data in the session, and at a different URL from the URL that was POSTed to. You should be able to use normal caching headers for this (search results) page, depending on how volatile your search results will be.

Vinay Sajip
By default, this won't help him, because if he 3xx-redirects to the other page, he's going to still get the "no-cache" request behavior.
EricLaw -MSFT-
Perhaps, but Post-Redirect-Get is still a good pattern to follow, and it's not clear that he is using it. As far as IE's vagaries go, I'm sure you are more familiar with them than I am ;-)
Vinay Sajip
Thank you for your response, Vinay. I am not using the PRG pattern at the moment.
ayaz
Vinay, thanks for pointing it. I decided to go with the PRG pattern. I was already storing data in the session before but not displaying on a different page that was being fetched via a GET by the browser. I added the redirect and get bits, and used the session data to display the results. This has worked for my requirements without having to rely on caching.
ayaz