PHPで制作中に気づいた。
フォームからPOST遷移で次のページに行ったあと、
そこでリロードしたり、もしくはさらに次のページから戻ってきた場合
「フォームの内容の再送信をするか?」と聞かれます。
再送で同じページが出てくるならそれで良いのですが、
場合によっては再送させたくないので、別ページにリダイレクトしたりする場合があります。
今回は「リロード時のみ別ページに転送したい」ということでやってみたんですが
iOSのsafariだと、「再送しますか?」の画面で固まって、それ以上の操作を受け付けませんでした。
—
form.php
<?php
session_start();
if($_SERVER['REQUEST_METHOD']=='POST'){
if(isset($_SESSION['token'])){
// トークンがあれば正常、トークンは削除
echo 'success';
session_destroy();
exit;
}else{
// トークンがなければエラーページへリダイレクト
header('Location: errer.html'); // デフォルトでは302でリダイレクト
exit;
}
}else{
// 通常アクセスの際にトークンを発行
$_SESSION['token']=1;
}
?>
<html><body>
<form action="" method="POST"><input type="submit" value="post"></form>
</body></html>
—
ところで、リダイレクトは
301 Moved Permanently
302 Moved Temporarily
の他にも
303 See Other
307 Temporary Redirect
というのがあるんですね。
本来ならPOSTして302リダイレクトが帰ってきたら、
リダイレクト先にもPOSTしないといけない(らしい)。
302の場合は
「POSTしましたけどー」「うちじゃないよ、転送先を当たってくれ」
なので、転送先にもあらためてPOSTすることを想定してる。
303の場合はPOST後にGETで見せたいなど、
「POSTしましたけどー」「処理は完了した、次にこっちを見てくれ」
という場合に使うんですね。
■ブラウザのPOSTリクエストは、リダイレクトさせるとGETに化ける? ::ハブろぐ
—
なので、もしかしたら303でリダイレクトしてやったらsafariも固まらないのか?と思いまして
header("HTTP/1.1 303 See Other");
header('Location: error.html');
exit;
としてみましたが、やっぱりsafariは固まりました。
—
となると、本来であればPOST後のページをform.phpで出すのではなく、
その時点でリダイレクトするというPRGパターン(POST-Redirect-GET)にしておけば良いんでしょうね。
(戻って固まるのは同じだが、頻度は減る?)
あとはそもそもリダイレクトしないことだな。