Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

navigate back with PHP form submission

Tags:

html

forms

php

So here is the deal, I am using HTML forms to transfer variables from page to page and PHP script to create pages based on values submitted. In general it looks like this: from the catalog of items you select what you want and the next page shows details for this specific item. Everything works perfect, except one thing:

Whenever I use browser's back button, I always get the error: ERR_CACHE_MISS and I need to refresh page and then confirm that I really want to resubmit data.

Is there any way to fix this, so my customers would be able just to use back button as they supposed to.

Here is the full text that browser provides me:

This webpage requires data that you entered earlier in order to be properly displayed. You can send this data again, but by doing so you will repeat any action this page previously performed. Reload this webpage. Press the reload button to resubmit the data needed to load the page. Error code: ERR_CACHE_MISS

like image 847
Maxim Ershov Avatar asked Oct 07 '13 00:10

Maxim Ershov


5 Answers

When you post forms with php, or any other data, you may come back to the page and find a message in the browser like "Document Expired" or "Confirm Form Resubmission With Chrome". These messages are a safety precaution the browser uses with sensitive data such as post variables. The browser will not automatically give you the fresh page again. You must reload the page by clicking try again or with a page refresh. Then, it operates as you would expect it to.

However, the php coder can work around the annoying message from the browser by adding a little code into the script. The example shows a couple of lines of code that can be added above session_start() in order to be able to go back and forth to the page when you post without any hangups.The 'private_no_expire' mode means that the client will not receive the expired header in the first place.

header('Cache-Control: no cache'); //no cache
session_cache_limiter('private_no_expire'); // works
//session_cache_limiter('public'); // works too
session_start();
like image 170
user3877861 Avatar answered Nov 15 '22 23:11

user3877861


**Some background: Credit goes to bruce (sqlwork.com) for his excellent explanation.

This web page requires data that you entered earlier in order to be properly displayed. You can send this data again, but by doing so you will repeat any action this page previously performed. Press Reload to resend that data and display this page.

Because of the sloppy coding practices of web developers browsers were forced to add this message. the scenario is as follows:

1) user fills in form and submits (posts form) 2) the server process the post data and responds with a new page (confirm) marked as not cacheable 3) the user navigates to a new page. 4) the user press back:

for the the browser to display the page in step 2, because its marked no-cache, it must request it from the server, in other words do the repost of the data (do step 1). here is were the sloppy coding came in, if this was an credit card charge, and repost detection was not on the server, the card is charged twice. this was (is) so common a problem, that the browsers had to detect this and warn the users.

the best fix is in step two, the server sends a redirect to the confirm page. then when the user accesses the confirm via history or back, its a get request, not a post request and will not show the warning.

note: webform's postback model lends itself to this problem. also avoid server transfers.

My solution

$_SESSION['home'] used to store any errors on home page.

$_SESSION['tempEmail'] used to echo value on php form.

Note: Use one unique session variable for each page that has a HTML form for error handling and also any session variable for each value that is echoed on HTML form.

<?php
session_start(); 

//Initialize variables not initialized without overwriting previously set variables.
if(!isset($_SESSION['home'])) {
$_SESSION['home']="";
$_SESSION['tempEmail']="";
}

Optional - If logged in, assign email address to the $_SESSION['tempEmail'] variable (if not previously done) to pre-fill HTML form.

if(isset($_POST['Submit'])){

---your code---


    //Error message(s) examples
    $_SESSION['home'] = "Email and Password do not match, please try again.";
    header("Location: " . $_SERVER['REQUEST_URI']);

    $_SESSION['home'] = "Email address format is invalid.  Please recheck.";
    header("Location: " . $_SERVER['REQUEST_URI']);

    //success
    unset ($_SESSION['home']); //optional, unset to clear form values.
    header ("location: nextpage.php"); 
             ---or---
    header("Location: " . $_SERVER['REQUEST_URI']);  //re-post to same page with the $_SESSION['home'] success message.   
}
?>



<body>

Error box

<span><strong class="error"><?php echo $_SESSION['home'] ?></strong></span>

HTML form

<form action="#" name="loginform" method="post" >
    <input type="text" name="userEmail" maxlength="50" title="Enter Your email" autocomplete="off" value="<?php echo htmlspecialchars($_SESSION['tempEmail']); ?>" placeholder="enter email" required/>
    <input type="submit" name="Submit" value="Submit">
</form>

</body>

Not recommended to use on payment page,see discussion above. Tested in Firefox, Chrome, Safari, and IE9. The annoying messages are gone when using back button. Ensure that output buffering is turned "on" in your php script or php.ini to avoid header warnings. You can check your php.ini file for the following;

output_buffering=On
like image 25
Medeno Avatar answered Nov 16 '22 00:11

Medeno


I found that using just :

header('Cache-Control: no cache'); //disable validation of form by the browser

resolve the problem

like image 8
Mimouni Avatar answered Nov 16 '22 01:11

Mimouni


None of the other answers worked for me.

  • I don't want to redirect
  • Setting different headers didn't work
  • I already use tokens in my post to ensure re-submission can't happen
  • I post to the same url the form is showing on

This simple javascript fixes my issue of the back button throwing "ERR_CACHE_MISS"

if ( window.history.replaceState ) {
  window.history.replaceState( null, null, window.location.href );
}
like image 5
Kapytanhook Avatar answered Nov 16 '22 01:11

Kapytanhook


I tried this answer and it's ok. You have to put this code before: session_start():

session_cache_limiter('private, must-revalidate');
session_cache_expire(60);

Good luck

like image 4
user5497991 Avatar answered Nov 15 '22 23:11

user5497991