DESIGN / CODE / INFRA / AI

解説

POSTの後はGET?そのままPOST?303と307のリダイレクトをローカルで確認

フォームのPOSTを受け取った後、別のURLへ移動させるとき。303と307は、どちらもリダイレクトだけれど、次のリクエストの扱いが違うよ。

POSTの後はGET?そのままPOST?303と307のリダイレクトをローカルで確認
保存リストを見る →
この記事の道しるべ 3項目

フォームのPOSTを受け取った後、別のURLへ移動させるとき。303と307は、どちらもリダイレクトだけれど、次のリクエストの扱いが違うよ。

ここでは、自分の端末内だけで動く小さなサーバーとcurlを使う。実際の注文・ログイン・個人情報は使わず、架空のexercise=demoという文字を送る練習だよ。

今回のPOSTでは、次のメソッドが違う

応答 移動先への今回の動作
303 See Other GETで取得する
307 Temporary Redirect POSTと本文を保って送る

303は、処理の後の別の結果ページを取得させる使い方がある。307は、メソッドと本文を変更せずに一時的な別の場所へ送る。

これは単なる画面上のURL変更ではない。移動先が何を受け取るかを考えて選びたいね。

ローカルで確かめる

Python 3とcurlがある環境で、練習サーバーを作業用フォルダーへ保存し、内容を確認してから実行する。

python3 server.py

127.0.0.1の8797番だけで待ち受ける。別のターミナルで次を実行しよう。

curl -sS -L --data 'exercise=demo' http://127.0.0.1:8797/start303
curl -sS -L --data 'exercise=demo' http://127.0.0.1:8797/start307

出力は、それぞれGET |とPOST | exercise=demoになる。編集部でも、このメソッドと本文の違いを確認したよ。--dataで最初のPOSTを作り、-Lで移動先を追っている。-X POSTを追加すると、curlへメソッドを強制する別の条件が加わるので、この比較では使わないでね。

終わったら、サーバーを動かしたターミナルでCtrl+Cを押す。8797番が使用中なら、--portで別の空いている番号を指定し、curl側のURLもそろえる。

何を保証していない?

303へ変えただけで、注文や課金が二重実行されなくなる保証はない。ブラウザの戻る操作、再試行、ネットワークの切断などを含む重複対策は、アプリケーション側でも設計が必要。

また、307で送信先を変えると、本文も送られる点が重要だよ。任意の外部URLへ認証情報や入力内容を転送するような作りにしないようにしよう。今回のサーバーは、同じローカルサーバー内の固定パスへしか移動させない。

URLの整理に使うcanonicalと301とは目的を分けて、処理後のメソッドとデータの扱いを確認してみよう。

参考・出典

公開と変更の記録
  • :初回公開

日時は日本時間です。記載のある変更は、確認できた編集記録に基づきます。更新日の違いだけから変更内容を推測して載せることはありません。

更新・訂正の方針 →

みんなのコメント 0

感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。

最初のコメントをどうぞ。