要約

  • 1996年5月のRFC 1945は302を「Moved Temporarily」と呼び、POSTの自動リダイレクトには利用者の確認を求めた。1997年1月のRFC 2068も慎重な規則を保ち、一部のクライアントがPOSTをGETに変えていたと記録し、GETで別の結果を取りに行く303「See Other」を定義した。
  • 1999年6月のRFC 2616は302を「Found」と呼び直し、既存の利用者エージェントの大半が302を303のように扱い、元の方法にかかわらず Location へGETしていたと書いた。方法の維持を明確にする307「Temporary Redirect」が加わった。303は1997年にすでにあった。
  • 2022年6月のRFC 9110は歴史的理由から302の後でPOSTをGETに変えることを今も許す。一方、307を自動でたどるクライアントは方法を変えてはならない。選択によってフォームの本文が移動先へ届くかが変わる。

一時移転は、何を運ぶかまで決めない

1996年5月のHTTP/1.0仕様、RFC 1945は302を「Moved Temporarily」と名付けた。求めた資源が今だけ別のURLにあり、サーバーは Location で行き先を示す。移転が変わるかもしれないため、次回も元のアドレスから始める。GETなら単純に見える。ここで文書を求め、仮の住所を教わり、そちらで読む。

POSTにはフォームの中身と利用者の行為がある。新しい住所が示されたからといって、同じ送信を繰り返してよいのか。1996年の文書は、POSTに302が返った場合、利用者が確認できないまま自動的にリダイレクトしてはならないと定めた。住所だけでなく、送信する相手と条件が変わり得るからだ。

リダイレクトには二つの判断がある。Location は次のリクエストの行き先を示す。メソッドと本文は、そこへ何をするかを決める。POSTのままなら入力内容が別のサーバーへ運ばれ得る。GETに変えれば新しい資源を読むが、元のフォームを再送しない。302を道案内だけと考えると、この差が消える。

初期仕様のブレーキは明快だった。送信ボタンを押した人が、別の宛先への再送まで承諾したとは限らない。その一方、サイトは送信後に結果ページを見せたい。ブラウザーは「仮移転」の返事を受けるたびに、次のリクエストをどう作るか選ばなければならなかった。

303はGETを明示し、ブラウザーは302でそれを行った

1997年1月のHTTP/1.1仕様、RFC 2068は、302の名称を維持し、GETやHEAD以外の自動リダイレクトには確認が必要だとした。注記には早くも食い違いがある。一部のHTTP/1.0利用者エージェントが、302を自動でたどる際にPOSTをGETへ変えていた。文書は自ら定めた規則に照らして誤った動作と位置づけた。

同じ1997年の仕様には303「See Other」もあった。POSTで起動した処理の結果を別のURIに置き、その資源をGETで取りに行かせる。最初の場所で行為が終わり、次の場所で結果を読む。新しいURIは元の資源の別名ではない。サーバーの作者にとって、303は「再送ではなく表示」を明瞭に伝える番号だった。

302をGETへ変えるブラウザーも似た画面を出せる。最初のPOSTが処理済みなら便利だろう。だがサーバーが仮の行き先で同じPOSTを続けるつもりなら、届くのは読み取り要求になってしまう。一つの番号に、結果ページの取得と操作の継続という二つの話が押し込まれた。1997年のRFCは、後世の分析を待たずにそのずれを記録している。

1999年、仕様が多数派のクライアントを認める

1999年6月のHTTP/1.1改訂版、RFC 2616は302を「Found」と呼び直した。より重要な注記は、1996年と1997年の規則はメソッド変更を認めていなかったのに、既存の利用者エージェントの大半は302を303のように扱い、元のメソッドが何であれ Location にGETした、と書いている。「大半」はRFC自身の当時の評価であり、個々のブラウザー版の数をこの資料から数えたものではない。

仕様はサーバーに選択肢を与えた。303はPOSTの処理後などにGETで別の資源を読む、という既存の指示だ。1999年の新顔は307「Temporary Redirect」。仮の場所へ行くが、元のリクエスト方法を保つという意図を明確にする。方法が変わればフォーム本文は新しい宛先へ再送されず、方法が保たれれば送信が続く。二つの番号はその境界を文章より短く伝える。

しかし302は消えなかった。RFC 2616は古いクライアントの多くが303を理解せず、互換性が必要なら302を使えるとさえ述べた。大半が303のように反応するからだ。明瞭な番号を用意した規格が、動いているブラウザーに合わせて曖昧な番号の利用も薦める。既存ソフトウェアの数が、紙の整った分類に圧力をかけた。

フォームを扱う人には具体的な利害がある。処理済みの送信の後で結果ページをGETするなら、本文を再び運ばない。操作を仮のURIで続けたいなら、POSTと本文を保つ必要がある。302だけに頼ると、次に何を送るかの一部をクライアントの歴史に任せることになる。

古い慣行が2022年の文書にも残る

2022年6月のRFC 9110「HTTP Semantics」は、302について歴史的理由から利用者エージェントがPOSTをGETへ変更してもよいと明記する。必ず変更せよという命令ではない。サーバーが変更を望まないなら307を使う。307を自動でたどる場合、クライアントはメソッドを変えてはならない。

同じ文書は303を間接的な応答として説明する。別の資源をGETやHEADで取得し、元の要求への答えとして示せる。歴史説明では、初期クライアントがPOSTを保つかGETへ変えるかで割れ、301と302ではGETへの変更が一般的になったと書く。仕様は広がった実装を見て語彙を変えた。

POSTを保つことが常に正しいわけでもない。307なら、フォーム本文は Location が示す新しい宛先へ運ばれ得る。同じ操作をそこへ移したいなら必要な動作だが、その宛先が誰の管理下にあるかは重要だ。GETに変更すれば本文を繰り返さない代わりに、本当に必要なPOST処理は行われない。番号は「新しいほどよい」で選ぶものではなく、二つ目の要求の役目に合わせて選ぶ。

これらの標準文書には、各ブラウザーがいつメソッドを変え始めたかという版ごとの一覧はない。日付付きの実装記録があればそこを確定できる。主要な順序は原文だけで追える。1996年の制限、1997年に記された逸脱、1999年の多数派認定と307、2022年の歴史的許容である。

移動したのはページだけではなかった

3xxを移転先の標識として描くことが多い。302の事件では、リクエストが運ぶ行為そのものが問題だった。POSTには利用者の判断とデータが載る。同じものを別のURIに送ることと、そこでGETすることは違う。Location は場所を指定し、状態コードとブラウザーが境界を越える内容を決める。

動いているクライアントが一つの答えを広めた。プロトコルの著者は古い指示を繰り返すだけではそれを消せなかった。ずれを記録し、メソッド維持を示す番号を加え、やがて302には歴史的なPOSTからGETへの変更を認めた。標準が相手にするのは、すでにネットワークにいるソフトウェアだ。

現在の読み分けは短い。302ではPOSTがGETになることがある。303は別の結果を読ませる。307は自動の仮移転でメソッドを保つ。同じフォームが三つの番号によって違う運命をたどる。古い番号だけが曖昧なのは、規格が書き直される前にブラウザーが動作を選んでいたためだ。

出典