POSTリクエストをリダイレクトするとGETされる?POSTされる?

あるURLにPOSTでリクエストを発行した結果リダイレクトされたとき,そのリダイレクトのリクエストはGETなのでしょうか?POSTなのでしょうか? なんとなくGETっぽいけど…

そこんとこどうなのか気になったので調べてみました.HTTPとかにはあんまりくわしくないので,おかしかったら指摘していただきたいです.

準備

リダイレクトが発生するレスポンスコードは以下の4つです.

  • 301 MOVED PERMANENTLY
  • 302 FOUND
  • 303 SEE OTHER
  • 307 TEMPORARY REDIRECT

HTTP1.1のRFCその解説によると,POSTリクエストした結果,レスポンスコードが302か307だった場合は,POSTでリダイレクトしたほうが良いようです.でも,ほとんどのクライアントはその決まりを守らずGETでリダイレクトしているとも書いてあります.

そこで,Firefox/Safari/Operaでそれぞれどういう振る舞いをするか調べてみました.

調査

調査用のHTTPサーバを動作させ,ログを監視して,リクエストメソッドとレスポンスコードを調べました.調査用のHTTPサーバは,以下のように動作するように仕込みました.(HTTP::Engineでちゃちゃっと書きました: http://gist.github.com/142163)

  • リクエストを受け付けたとき
    • redirectパラメータにステータスコードが設定されていたらそのステータスコードをかえす
    • redirectパラメータが設定されていなかければステータスコード200を返す

このサーバに対してredirectパラメータに301/302/303/307を設定したPOSTリクエストをそれぞれ発行し,その後のリダイレクトによるリクエストがどのメソッドによって行われているかを調査します.

結果

返されたステータスコードが302や307であってもOpera以外のブラウザはリダイレクトの際GETによってリクエストを発行するようです.Operaは307の場合だけPOSTでリダイレクトを行おうとしました.

Firefox3.5 Safari4 Opera9
301 GET GET GET
302 GET GET GET
303 GET GET GET
307 GET GET POST

Operaで307が返されたときは"警告: フォームPOSTリダイレクト"という普段見慣れないダイアログが表示されました.


まとめ

あるURLにPOSTでリクエストを発行した結果リダイレクトされたとき,そのリダイレクトのリクエストはほとんどの場合GETであることがわかりました. Operaの307はかなり特殊なパターンです.Webアプリケーションを作成する際には,POSTのリクエストをリダイレクトして,そのまま別のURLにPOSTさせるということはできないと思っておいたほうが良さそうですね.