Understanding the "post/redirect/get" pattern

I'll try explaining it. Maybe the different perspective does the trick for you.

With PRG the browser ends up making two requests. The first request is a POST request and is typically used to modify data. The server responds with a Location header in the response and no HTML in the body. This causes the browser to be redirected to a new URL. The browser then makes a GET request to the new URL which responds with HTML content which the browser renders.

I'll try to explain why PRG should be used. The GET method is never supposed to modify data. When a user clicks a link the browser or proxy server may return a cached response and not send the request to the server; this means the data wasn't modified when you wanted it to be modified. Also, a POST request shouldn't be used to return data because if the user wants to just get a fresh copy of the data they're forced to re-execute the request which will make the server modify the data again. This is why the browser will give you that vague dialog asking you if you are sure you want to re-send the request and possibly modify data a second time or send an e-mail a second time.

PRG is a combination of POST and GET that uses each for what they are intended to be used for.


Wikipedia explains this so well!

The Problem

The Problem

The Solution

The Solution


As you may know from your research, POST-redirect-GET looks like this:

  • The client gets a page with a form.
  • The form POSTs to the server.
  • The server performs the action, and then redirects to another page.
  • The client follows the redirect.

For example, say we have this structure of the website:

  • /posts (shows a list of posts and a link to "add post")
    • /<id> (view a particular post)
    • /create (if requested with the GET method, returns a form posting to itself; if it's a POST request, creates the post and redirects to the /<id> endpoint)

/posts itself isn't really relevant to this particular pattern, so I'll leave it out.

/posts/<id> might be implemented like this:

  • Find the post with that ID in the database.
  • Render a template with the content of that post.

/posts/create might be implemented like this:

  • If the request is a GET request:
    • Show an empty form with the target set to itself and the method set to POST.
  • If the request is a POST request:
    • Validate the fields.
    • If there are invalid fields, show the form again with errors indicated.
    • Otherwise, if all fields are valid:
      • Add the post to the database.
      • Redirect to /posts/<id> (where <id> is returned from the call to the database)