KBD

Keith Devens .com

Sunday, October 12, 2008 Flag waving
Of all tyrannies a tyranny sincerely exercised for the good of its victims may be the most oppressive. It may... – C.S. Lewis
← Double check pictures of your house you put on the InternetZope.org - Formulator →

Daily link icon Saturday, August 28, 2004

Testing PRG

Testing a small change to my comment posting. I might as well explain what it is:

Using the POST-redirect-GET pattern (PRG) for web forms means that after a POST form submission, you then do a redirect so that the POST "goes away". By "goes away" I mean that if you hit refresh or go back and forward in your browser history it won't ask you to re-submit form data. This protects against duplicate POSTs and helps to prevent annoying the "user".

In addition, consider the case of my weblog comments. Unlike some weblog systems, the form to post comments is right on the weblog entry page itself. If you don't do a PRG then a person will not be able to refresh the page to see if anyone's responded to his comment without getting the POST resubmit popup. This is how it was on my site for a long time, and the only way around this was to navigate off the page and then navigate back to it. This is extremely inconvenient. So, I implemented PRG in my Formation library and then on my site.

The problem was this: the result of POST requests is never cached, so if you do a POST you'll always get fresh data. But, GET requests can be cached, so if your caching is set up a certain way you can do a POST to add a new comment, but then when you're redirected as part of the PRG you won't see the comment you just left. To get around this I added a kludge so that when you left a comment you were redirected back to the same page, except with "?newcomment=$comment_id" appended onto the URL. This is probably one of these cache busting techniques. That way, you'd be requesting a "new" page every time and be guaranteed to see fresh data.

At some point recently I've removed all caching headers from my site because I couldn't come up with a good caching scheme. Some of the things that made it hard for me to figure out the right caching scheme was that because my pages are mostly static I'd want them to have a pretty generous caching scheme, possibly even "public", but then if a new comment was posted people might not see it (in either the "recent comments" section on the right, as an increment to the comment count under a post, or as a new comment displayed on individual entry page). In addition, when I'm logged in to my site as an administrator, next to every post I get a little edit button that lets me easily edit that post. If I had very generous (like public) caching set up, after I logged in I'd have to do a "hard refresh" of the page contents to make the edit button show up.

I expected to go back and figure out the most appropriate scheme later, but it turns out the browser's default caching seems to behave exactly how I want it to. Back and forward don't cause the page to be refetched, so you get some of the benefits of caching, but when you navigate around it fetches a new page, so my edit buttons show up. There's even the case where you start typing in a textarea, go to another page, and then come back, and the text you typed is still filled in. With a stringent caching scheme (like no-store, no-cache, must-revalidate), that text would be wiped, but with the default caching scheme it's not. (Update: oops, I was wrong, it is wiped. However, I don't think you can have it both ways. i.e. have text not be wiped and have the behavior I describe next regarding my weblog entry form.) This also applies to my weblog entry form I'm typing in. With generous caching, if I edited an entry, saved it, and then went to edit it again, I'd get the entry as it was before I last edited it. If I made a change to the entry the second time the first change's changes would be overwritten. To get around this I'd have make sure to do a hard refresh on the weblog entry screen when re-editing posts, but with the default caching scheme this isn't a problem.

Anyway this post is here for me to do a test to see if I still need that "?newcomment=$comment_id" kludge to have new comments show up after you post them and you're redirected.

Update: And it works in both Internet Explorer and Firefox, but Opera seems to have issues. In fact, Opera is leaving the connection open even after it says "Completed request to keithdevens.com" in the status bar and is not refreshing the page. It's strange.

Update: I have no clue what Opera is doing. It seems to just be inexplicably leaving the connection open. If I preview (which doesn't do the redirect after post) and then post the comment it doesn't have the problem. Oh well, screw Opera. Incidentally, Opera uses weird headers I've never heard of, like Cookie2 and TE.

← Double check pictures of your house you put on the InternetZope.org - Formulator →

Comments XML gif

Keith (http://keithdevens.com/) wrote:

testing

Keith | 28-Aug-2004 5:29am est | http://keithdevens.com/ | #5375

Keith (http://keithdevens.com/) wrote:

Testing in Internet Explorer.

Keith | 28-Aug-2004 5:30am est | http://keithdevens.com/ | #5376

Keith (http://keithdevens.com/) wrote:

Testing in Opera.

Keith | 28-Aug-2004 5:31am est | http://keithdevens.com/ | #5377

Keith (http://keithdevens.com/) wrote:

Testing in Opera again.

Keith | 28-Aug-2004 5:31am est | http://keithdevens.com/ | #5378

Keith (http://keithdevens.com/) wrote:

Testing in Opera one more time.

Keith | 28-Aug-2004 5:32am est | http://keithdevens.com/ | #5379

Keith (http://keithdevens.com/) wrote:

Testing in Opera for the last time.

Keith | 28-Aug-2004 5:32am est | http://keithdevens.com/ | #5380

Keith (http://keithdevens.com/) wrote:

Testing with Ethereal so I can try to figure out what Opera's doing.

Keith | 28-Aug-2004 5:37am est | http://keithdevens.com/ | #5381

Keith (http://keithdevens.com/) wrote:

Testing one more time with Ethereal and Opera.

Keith | 28-Aug-2004 5:46am est | http://keithdevens.com/ | #5382

Keith (http://keithdevens.com/) wrote:

And one more time with gzip compression off.

Keith | 28-Aug-2004 5:49am est | http://keithdevens.com/ | #5383

Arnaud wrote:

A possible technique to re-submission is to put a token in a hidden field. If the page is resubmitted you check if the token was used, if you so you don't take into account the user action.

like

input hidden value=48a24b70a0b376535542b996af517398

on the server you create a file with the name as the value above when the form is submitted. Checking if a file with a name as token value you don't take into account the submission.

∴ Arnaud | 31-Aug-2004 1:50pm est | #5420

Keith (http://keithdevens.com/) wrote:

Arnaud, I know there are many ways to protect against duplicate form submission, but that's only one benefit of the PRG pattern. The main one is getting rid of the "Resubmit this form data?" popup, which also allows you to use the back and forward buttons in your browser despite a form submission.

Keith | 31-Aug-2004 2:04pm est | http://keithdevens.com/ | #5422

Levin wrote:

Testing with Opera

∴ Levin | 31-Aug-2004 3:49pm est | #5430

Arnaud wrote:

Yes true, I was a bit off topic but it may help some people reading it (who knows Smiley

I've noticed though that when using a token I would not get the resubmitted popup though I haven't looked into it too much.

∴ Arnaud | 31-Aug-2004 5:48pm est | #5437

Ian Bicking (http://blog.ianbicking.org) wrote:

There's a number of 3xx redirect codes, some of them work better than others. I think 303 is the right one for PRG. I've found that other ones work, but sometimes act funny.

∴ Ian Bicking | 1-Sep-2004 12:07am est | http://blog.ianbicking.org | #5443

Feel free to post a comment below. Please see my comment policy.

Formatting Rules (No HTML):

  • **bold**, *italic*, _underlined_, --strikeout--
  • "text"="url" creates a link, and URLs are auto-highlighted
  • Blockquote: Like e-mail, begin paragraph with > (greater-than sign)
  • Lists: begin paragraph with *,-, or + (unordered), or # (ordered)
  • Code block: ?!code:language=perl|php|sql|javascript|etc.{\n}...{\n}?!/code

:
(will be your IP address if blank)
: (optional)
(Will not be shown on site)

: (optional)
:

October 2008
SunMonTueWedThuFriSat
 1234
567891011
12131415161718
19202122232425
262728293031 



RSS feed RSS feed for Keith's Weblog
Atom feed Atom feed for Keith's Weblog
Weblog archive
Recent comments
  on 7 posts

Recent comments XML

I hate PHP

Elliot Anderson,

Dude!! You the​man! The reverse replacement for​array_u...

Alex Ndungu: Oct 11, 1:35am

Call a function from a string in Python

?!code:
some_object.__getattribute​__('method_name')()
?!/code

is​the s...

Patrick Corcoran: Oct 8, 3:53pm

Spider solitaire

I have won 185 games of Spider​Solitaire at the "Difficult" level.​ What is...

75.179.28.113: Oct 8, 12:42pm

Sed one-liners

Hi.

I wanted to let you know​that I wrote an article "Famous Sed​One-Lin...

Peteris Krumins: Oct 8, 3:05am

Timesheet Calculator

Hadn't seen it before now, but my​company already uses a time​tracking prog...

Keith: Oct 7, 10:44am

Girls, please don't get breast implants

Hey everyone, 

I am new to this​blog and I have enjoyed reading all​your...

Sarah.M.: Oct 6, 9:45am

Generated in about 0.176s.

(Used 8 db queries)

mobile phone