Apache fix for IE “webpage has expired” on back button

When you refresh a webpage that was the result of a HTTP POST, your browser asks you if you want to reload.

The reason for this dialog is to stop the user from inadvertently submitting the same blog post/email message/payment details multiple times. That behaviour is standardised across all browsers. What's not standardised is what happens when you use the "Back" button to navigate to a previous POST page. In most browsers, you get the page from your cache. In IE, you get the dreaded "webpage has expired":

The intention here is good. This is a fool proof mechanism for keeping the user from submitting that page again. But what if your site can actually handle that? Why break the back button this way? A good counter example is a search engine. The search string may be sent via HTTP POST, but you would still like the user to be able to hit "back", change the search string, and hit submit again. In IE, you need a work-around for this.

The most common work-around is to redirect the POST to a GET on the server side, aka the PRG Pattern. This adds some back-end code, but generally solves the problem. However, it can get complicated if you are doing server-side validation, as you generally want to show the form again with validation exceptions in that case. So then you have to persist the temporary state of the FORM in either the session state or the database... messy.

Another solution is to use GETs in the first place. This is ok for some things, like Google searches, but does not work if you need to pass a lot of form data between pages. Also, it ignores the principle of idempotence, which for HTTP means that you should not use GETs for state-changes.

The work-around I have been using recently is to not send a Vary header for IE only.

The Vary field value indicates the set of request-header fields that fully determines, while the response is fresh, whether a cache is permitted to use the response to reply to a subsequent request without revalidation.

In Apache, this is a simple configuration change in httpd.conf:

BrowserMatch MSIE force-no-vary

The practical effect is that when you go "back" to a POST, IE simply gets the page from the history cache. No request at all goes to the server side. I would be interested in hearing about potential down-sides of this solution, other than the fact that the user can submit the form twice. In my case, this is handled already by the CSRF token.