views:

73

answers:

3

I'm got a comment form for an article and i'd to prevent re-submission. I notice that Worpdress handles this very well (going back doesn't cause the browser to request a form re-submission), but I can't figure out how they do it, even though our methods are very similar.

My Script

User visits mydomain.com/article/1/article_title.html

Fills in a form which posts to mydomain.com/addnewcomment/1.html

I then do a 302 redirect back to mydomain.com/article/1/article_title.html

Now if I press back from this position it doesn't request a redirect. However, if I go to another page e.g. mydomain.com/tag/1/my_tag.html and press back it does resubmit the form.

Obviously I want to prevent this.

What Wordpress does

User visits mydomain.com/?p=1 Fills in a form which posts to mydomain.com/wp-comments-post.php This then does a 302 redirect back to mydomain.com/?p=1

Pressing back or visiting another page and pressing back doesn't cause a re-submission.

I've had a look through the WP code but I can't see how they manage this. Obviously it's something i'd like to achieve.

Does anyone have any thoughts on where I may be going wrong?

(I'm only using Wordpress as an example to prove that it's possible, obviously i'm not trying to exactly duplicate WP, that would be pointless)

EDIT - Figured out what it was

I haven't nailed exactly which header it was, but I was sending additional headers before doing the redirect (problem with my code, calling one function before the redirect, when really I should have called the redirect first).

After I moved the function and stopped sending these headers before the redirect it worked fine, without resubmissions after going back.

Of course it's important to check for duplicates as well, but this stops the browser ever popping up with a form resubmit request which is what I wanted.

The headers I was sending where:

Content-Type Last-Modified Etag Content-language Cache-Control Pragma Expires

I'm guessing it was probably something to do with pragma no-cache or must-revalidate in the cache control header.

Either way, if you're having the same problem, check what other headers you're sending before the redirect.

+1  A: 

http://en.wikipedia.org/wiki/Post/Redirect/Get

simplemotives
Cheers for the link, but I can't see how it's that different to what i'm doing. I'm doing a 302 redirect to a new location, but when I visit another page and then go back the browser seems to load the form, even though the form action wasn't done from this page.If I log every page to a txt file, it seems that even when I press back and hit the article page the browser still calls "mydomain.com/addnewcomment/1.html" first.
Rob
A: 

Add a hidden field to your form with a large random number, or if you want to go really crazy, a timestamp with a random number appended.

Then store this number with the post, and double check if that number has been used before. If so, don't repost.

This also handles all of the situations that PRG cannot solve, i.e. (from the wiki):

  • If a web user goes back to the web form and resubmits it.
  • If a web user clicks a submission button multiple times before the server response loads
  • If a web user refreshes before the initial submission has completed
Jeff B
WordPress does more than this. It won't let you post a duplicate comment, even after a PRG and a new random number. I think it must actually compare the comment text.
Craig Stuntz
that could be a problem tho. say you want to post "happy birthday" and then "happy birthday" just for fun, it won't let you do that
ggfan
A: 

This is why I prefer using UUIDs as my table row keys. For a problem like this, I would generate the row key in the blank comment field, as a hidden field. Then if somebody tries to refresh or hits back & submit, the INSERT will fail because the key already exists.

TravisO