Andy Pemberton Rotating Header Image

The Post Redirect Get Pattern

Sometimes I look at old draft blog entries and ask myself “what was I thinking?”. Every once in a while, though, I look at an old draft post and say “hey, that’s pretty cool!”. This article fell into the pretty cool category, not so much for the content, but the example app, so I hope you enjoy it (OK, you can skip to the end now).

There’s a long-standing, accepted pattern for handling form submissions in web applications; it’s usually called the post redirect get pattern. The goal of the pattern is to prevent the payload of a HTTP POST request from being stored in the browser history.

Keeping the POST data out of the browser history helps prevent duplicate form submissions and also is the best way to make sense out of navigating backward/forward through the history after a post. Imagine refreshing a webpage without the PRG pattern after making a credit card purchase.

To speak in HTTP terms, the PRG pattern intends to handle the non-idempotent nature of the POST method. As defined by the HTTP specification, it’s not safe to submit the same POST data more than once, so the PRG pattern prevents the user from resubmitting POST data when refreshing their browser window or navigating through their browser history.

As I mentioned, this is a long-standing pattern and as such, there are several references available that describe it in full detail:

It is also widely implemented in most modern web application frameworks (eg: JBoss Seam, Ruby on Rails) and because it avoids problems caused by HTTP itself, it is implemented in various web-specific languages/frameworks (JavaEE, .NET, PHP, Python, Ruby, etc).

Example Application

OK, so why did I think this post was worth finishing? Well, many moons ago, I built out an example application in PHP demonstrating the post redirect get pattern.

Hope you find it useful.

8 Comments on “The Post Redirect Get Pattern”

  1. #1 Chris Wash
    on Mar 10th, 2009 at 10:39 am

    Cool!

    I think 303 what should be returned under normal circumstances. http://en.wikipedia.org/wiki/HTTP_303; same with PUT for REST-style services.

    I wonder if there is a quick/dirty crawler that will look for forms and do some POSTing, and let you know if it gets a 200 back from any of them. I know of a few commercial tools. Maybe another little tool to write into my web testing swiss-army-knife?

  2. #2 Daily del.icio.us for March 11th through March 14th | Vinny Carpenter's blog
    on Mar 14th, 2009 at 4:06 pm

    [...] The Post Redirect Get Pattern – Andy Pemberton - There’s a long-standing, accepted pattern for handling form submissions in web applications; it’s usually called the post redirect get pattern. The goal of the pattern is to prevent the payload of a HTTP POST request from being stored in the browser history. [...]

  3. #3 bill p
    on Aug 11th, 2009 at 1:43 pm

    Andy,

    Very helpful example. This may be a dumb question but what does the code for prg_redirect.php look like?

    Bill

  4. #4 Andy Pemberton
    on Aug 11th, 2009 at 2:42 pm

    No problem, Bill. It’s pretty basic PHP to set the selected HTTP redirect status code:

    < ?php
    function HTTPStatus($num) {
    static $http = array (
    301 => “HTTP/1.1 301 Moved Permanently”,
    302 => “HTTP/1.1 302 Found”,
    303 => “HTTP/1.1 303 See Other”,
    304 => “HTTP/1.1 304 Not Modified”,
    305 => “HTTP/1.1 305 Use Proxy”,
    307 => “HTTP/1.1 307 Temporary Redirect”
    );
    header($http[$num]);
    }

    $status_code = $_REQUEST['redirect_status'];
    if(!$status_code) $status_code = “301″;
    HTTPStatus($status_code);
    header(”Location: prg_view.php”);
    ?>

  5. #5 Rylie B
    on Oct 1st, 2009 at 11:06 pm

    Hi, Andy. Thanks for sharing this. Can you make your example code downloadable? - Rylie

  6. #6 Milos
    on Oct 20th, 2009 at 7:55 am

    Except that 307 Temporary Redirect WILL cause my browser to issue a warning about resubmitting the post. Because 307 will use POST and not GET method.

    Please put this line in prg_view.php:

    echo ‘Method: ‘,$_SERVER['REQUEST_METHOD'];

  7. #7 Andy Pemberton
    on Oct 21st, 2009 at 1:17 pm

    Thanks @Milos. I actually mentioned that in the example application, but not this article itself:

    The following redirect status codes, however, yield unpredictable results:

    * 304 Not Modified
    * 305 Use Proxy
    * 307 Temporary Redirect

  8. #8 Katrien De Raedt
    on Feb 15th, 2010 at 11:14 am

    And how do I implement that code in my existing code ? I have several lines using ‘if(isset['$_POST']….

Leave a Comment