How to avoid POSTDATA resend warning

"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_mozilla

POSTDATA resend warning in Mozilla Firefox

POSTDATA_resend_ie

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');
}
?>

 
In the target page, when showing the success message, we can get the information from SESSION easily.
 
Hope this will solve your problem. Please tell me if any confusion or question with this article.  See you again.

37 Comments

  1. @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.

  2. 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

  3. 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.

  4. 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.

  5. 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.

  6. Can any body guide me how i can use code(on which location i have to paste) to get rid of this problem.
    thanks

  7. 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;

  8. 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’);
    }

  9. @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

  10. 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

  11. 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

  12. 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?

  13. 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 🙂

  14. 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.

  15. In the URL window of firefox type about:config
    Change this setting in firefox
    browser.sessionstore.postdata
    Change from a 0 to 1

  16. Nice article, but I don’t belive data is posted when using the history buttons, only on refresh.

Leave a Reply to stojce Cancel reply

Your email address will not be published. Required fields are marked *