"POSTDATA resend" warning is a common problem when developing web applications. Before discussing about the solution, let’s know what is the problem actually and when it arises.
About the problem :
We see this warning when we try to revisit a page that has accepted POSTDATA using browser’s history mechanism. Usually we do it by browser’s BACK button or refreshing a page. When a page in browser history requested with POST method, the browser thinks this POSTDATA is important to process this page. So, it asks the user if he wants to send the POSTDATA again or not. Different browsers show this warning differently. For example, the images below shows how Firefox and Internet Explorer show this warning.
POSTDATA resend warning in Mozilla Firefox |
POSTDATA resend warning in Internet Explorer |
Now, If the user accepts the confirmation, the page is reloaded with previously sent data using POST method; otherwise some browsers don’t take any action and some shows a "Webpage has expired" message. In some situations, this re-submitting is useful, but most of the times it’s not expected. It’s more harmful when user accepts it without understanding and causes multiple entries of previously entered data in database.
The easy solution :
The easy solution is simply redirecting. When we redirect a page, the target page is loaded without any POST data that comes with request.
Let’s solve this problem by hand. Say we have 2 pages – A and B. A has a feedback form which submits data by POST request method to B. B inserts the information into database and shows a success message.
Now, if the user try to reload the page by refresh, back button or any other way, browser will show the confirmation message. If user accepts this, the message will inserted again. But after inserting to database, If we redirect to another page C and C shows the success message, the problem will not occur. Because, in the final output to the browser will come from C which didn’t use any POST request data. The code should be something like this:
<?php
if($_POST)
{
/* Form validation, Inserting to database or anything you want goes here */
/* Now redirect to another page */
header('Location: http://yoursite.com/success.php');
}
?>
Extending the solution :
The solution I explained above can show just an static message like "Thanks for your feedback" or "Registration completed successfully" etc. But usually we like to include some information about sender or submitted information in the success of failure message. For example:
Hi Andrew, your registration is successfully completed. An email is sent to you at andy001@yahoo.com with more information.
In the above message, the purple colored information has to be taken from POST data. But the POST data will be lost when redirecting. So, it’s not possible by the above solution.
What we can do to solve this is that we can use SESSION to store those data which we want to display with message in redirected page. Just like this:
<?php
session_start();
if($_POST)
{
/* Form validatio, Inserting to database or anything you want goes here */
//Store data to session
$_SESSION['name'] = $_POST['name'];
$_SESSION['email'] = $_POST['email'];
//Now redirect to another page
header('Location: http://yoursite.com/success.php');
}
?>
After assiging session varaibles you have to unset this variables in the success.php.
You’ve not quoted it.
Thanks.
I think this pattern is still new to a lot of web developers.
Wikipedia: http://en.wikipedia.org/wiki/Post/Redirect/Get
Simpler solution:
@Panucci & stojec: Thanks a lot.
@Jahedur Rahman: It’s depending on for which purpose the script is being used.
Sometimes you should unset it just after displaying a successmessage. But remember that, for the example used here, after u unset this values from session, the message will be shown without name and email address.
there is a component for Java web developers with Redirect after POST pattern: http://www.servletsuite.com/servlets/redirectafterpost.htm
In this simplistic example you’ve prevented the POSTDATA warning. But the code under “extending the solution” introduces a bug.
What happens when the user refreshes the success page after the PHP session expires?
$_SESSION[‘name’] and $_SESSION[’email’] will be unset!
This redirect method is safer:
//Now redirect to another page
header(‘Location: http://yoursite.com/success.php?name=blah=email=blah@hotmail.com’);
Of course ensure values are url-encoded
Hi Quinton,
Thanks for this solution. It’s really a lot easier. When I m sure that, no special character will occur in values, I also use this post/redirect/get technique.
For the current solution, when u will unset the session is depends on functionality of your script. If there is no specific reason, you shouldn’t unset the session values immediately. And for some situation, say if you redirect to current page, you have to unset it immediately after displaying and message and should check if the session is set before displaying message each time.
Thanks again for your comment.
Nice effort
i keep on having POSTDATA when i refresh
A really easy untech way to solve this problem is to start firefox in safe mode and check the box to delete add-ons. Somehow we had add-ons of Talkback and Skype, neither of which we put on. Once they were removed, no more Postdata message. I think the problem was caused by skype.
Like oscar, I’ve used this pattern before and under some server setups, I continue to see POSTDATA messages even after the redirection. I’ve not confirmed that this is the case, but I think IIS and Apache work differently with respect to this pattern.
Can any body guide me how i can use code(on which location i have to paste) to get rid of this problem.
thanks
how about doing this via javascript – refresh the current location minus post variables:
// or make variable & convert to string
refresh = parent.location;
// assign location as this string
parent.location = refresh;
Good
Thanks.
It help me very much
Ive use this in the past
try it out, but it only seems to work for IE and will break with a refresh
Can anyone make it work for firefox
I use this php
if ($_SERVER[‘REQUEST_METHOD’]==’POST’)
{
header(‘Expires: ‘ . gmdate(“D, d M Y H:i:s”, time()+1000) . ‘ GMT’);
header(‘Cache-Control: Private’);
}
@datafake:
Thanks for commenting.
Here all the tasks are being done from php. So, how can it be different for IE and FF?
And, in your second comment, you’ve written a code snippet which have no effect on this technique.
Can u plz try this (either using my technique or as said in comment:7) once again for FF?
Thanks
Hi, there.
What Ive suggested is an completely alternative solution I found that doesn’t involve a redirect. It isnt as complete a solution as yours but I think its relevant to the discussion.
If you POST some variables to a PHP page that has my snippet at the top.
Then go to a new page.
Then go back.
You will not get the resubmit POST warning in IE. You will just see the cached output that was generated.
If you then refresh you will get the resubmit warning.
Its my technique that doesnt work in firefox presumably because it must handle the headers differently.
Thanks
thank u
Thnx datafake, your tip was very usefull. Explorer isn’t 😉
Hi there,
One thing to keep in mind, is that your HTTP status code should also be 303 rather than 302, so that it is standards compliant AND future safe for new browsers that may come out.
This is easily doable by modifying:
header(‘Location: SUCCESSPAGE’);
to
header(‘Location: SUCCESSPAGE’, true, 303);
Cheers,
Sam
can someone tell me bout these codes?
u guys keep mentioning them on how to redirect
the web page but not how use them, can someone help me out?
I found this post, and it got my noodle cooking – heres what I came up with.
Rather than using one or more other pages, after submission, I usually reuse the same page, do validation db inserts and what not.
In the top of your whatever.php place this:
session_start();
if ($_SERVER[“REQUEST_METHOD”] == “POST”) {
$_SESSION[“__POSTFIELDS”] = serialize($_POST);
header(“Location: ?check”);
}
else {
if (strlen($_SESSION[“__POSTFIELDS”]) > 0) {
$_POST = unserialize($_SESSION[“__POSTFIELDS”]);
}
}
This way, we keep track of all the postdata, and re-assign them to $_POST so we can proceed with our validation stuff, like so:
if ((isset($_GET[“check”])) && (strlen($_SESSION[“__POSTFIELDS”]) > 0)) {
if (strlen(trim($_POST[“usr”])) < 1) {
echo “Username missing.”;
}
if (strlen(trim($_POST[“pwd”])) < 1) {
echo “Password missing.”;
}
}
Also the form fields gets their values re-assigned using the appropriate post field.
In case this doesn’t make any sense, you can see my example here:
http://sandbox.datapimp.dk/post/
I must admit i haven’t tested this completely yet, so it might have one or more drawbacks 🙂
You can think up how ever number of solutions but the problem will still remain; you are only really masking it.
The best course of action is just to do a redirect after POSTing data and be done with it – just accept that there are going to be people out there who will abuse how the HTTP protocol works.
@Les
“The best course of action is just to do a redirect after POSTing data” 😀
Did u actually read this post?
thanks subfatal. It works, i’ll be testing it
sorry i wrote it wrong (zubfatal)
In the URL window of firefox type about:config
Change this setting in firefox
browser.sessionstore.postdata
Change from a 0 to 1
Nice article, but I don’t belive data is posted when using the history buttons, only on refresh.
You seem to be a very well versed writer – have you taken any classes or courses? I’m impressed -Aracelis Mccarney
this good…
you explain it very complete …
I was greatly assisted…
thx.
Greetings from Sydney. Thanks for the useful data. I’m doing a project at uni and your content was quite useful. Thanks for sharing 🙂