1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

リダイレクトの歴史 〜HTTP3xxリクエスト完全理解〜

1
Last updated at Posted at 2025-09-03

研究でリダイレクトの仕組みについて歴史的背景を調べてみました。もしよければ参考にしてください。

そもそもなぜリダイレクトの仕組みが整備されたの?

まず、リダイレクトというのはリクエストがあった場合に、そのページが存在しない時、あるいはあったとしても推奨されない宛先だった場合に「こっちに来てくださいね〜」というための仕組みです。

例えばhttp://www.google.com と打つと https://www.google.com (sあり)に送られるアレです。

このときの裏側の仕組みとして、まずブラウザは www.google.com にhttpでリクエストを送ります。するとブラウザは「だめだ、それじゃセキュリティ上懸念があるのでhttpsでよろしく」といってgoogle のサーバが https://www.google.com に送り返すように依頼が来ます。
このような適切な宛先への送り出しの仕組みがリダイレクトというやつです。

初期のWeb(1990年代)は、Webサイトの構造がよく変わる時代でした。ちょっとページを別のディレクトリに移したり、ドメインを変えたりするだけで、古いリンクは「404 Not Found」になってしまって大変だったようです。
せっかくリンクをクリックしても、すぐにurlが変更になるとUXが非常に低下してしまいます。というわけで標準化が進みました。

301 302 304リクエストの登場

最初の標準化の仕組みは1996年、RFC1945で整理されました。
こちらで仕様が定められたのが
| "200" ; OK
| "201" ; Created
| "202" ; Accepted
| "204" ; No Content
| "300 " ; Multiple Choices
| "301" ; Moved Permanently
| "302" ; Moved Temporarily
| "304" ; Not Modified
| "400" ; Bad Request
| "401" ; Unauthorized
| "403" ; Forbidden
| "404" ; Not Found
| "500" ; Internal Server Error
| "501" ; Not Implemented
| "502" ; Bad Gateway
| "503" ; Service Unavailable

の16個のリクエストです。

あれ?303が欠番になってる?
そうです。というかほかにもいくつか欠番になっています。(402とか)

image.png
確かにここでは303は定義されていませんよね。

ともかくこのRFCでリダイレクトの仕組みの中で

301:Moved Permanently(恒久的な移動)
→RFC「要求されたリソースには新しい恒久的なURLをが割り当られている。今後そのリソースへの参照はその新しいURLを使って行うべきである」
→「送信先が変わっているので、そしてそれは恒久的な変更であなたが渡してくれたアドレスは蘇ることはないので、可能なら次やるときは新しい方に送るようにしてね」という応答

302:Moved Temporarily(一時的な移動)
→RFC「要求されたリソースは一時的に別のURLにある。将来のリクエストでは引き続き元のRequest-URIを使うべきである。」
→「一時的リダイレクトです。サーバー側が「今だけ別のURLに置いてる」場合に使います。渡してくれたアドレスは蘇るかもですが今はこちらに来てください」という応答

304:Not Modified(変更なし)
→クライアントが条件付きGET(If-Modified-Sinceヘッダを指定)を行い、アクセスは許可されたが、リソースが指定された日時以降変更されていなければ、サーバーはこのコードを返し、本文を送信してはならない。
→「キャッシュしてるバージョンで十分、新しいデータはない」という応答

が定義されました。(300 Multiple Choicesは宛先の候補が複数あるよ、というただの通知の役割で特に存在感は薄いので省略します)

どのようなときに使われるのかが気になると思うので、具体例を与えましょう。

🔹 301 Moved Permanently(恒久的な移動)

利用例
・Webサイトの構造変更
http://example.com/old-page.htmlhttp://example.com/new-page.html に変更された場合(古いURLにアクセスすると301を返し、そのレスポンス内のLocationヘッダというところに新しいURLを指定する)
・HTTPS化を強制したいとき
http://example.com/ にアクセスしたら https://example.com/ に301でリダイレクトを送る。
・ドメインが移転したとき
http://oldsite.com/http://newsite.com/ に変わった時

🔹 302 Moved Temporarily(一時的な移動)

具体的なケース
・メンテナンス時の一時移動
http://example.com/service がメンテ中 → http://backup.example.com/service に302で飛ばす。
・A/Bテスト
ユーザーをランダムに http://example.com/test1 または http://example.com/test2 に振り分ける。
・ログイン処理
フォームに入力 → 認証後に 302 Found を返し、ユーザーを /dashboard に一時的に移動させる。

🔹 304 Not Modified(変更なし)
具体的なケース
・ブラウザがキャッシュを利用する場合
ブラウザ: If-Modified-Since: Wed, 01 Sep 2025 10:00:00 GMT
サーバー: リソースが更新されていなければ 304 Not Modified を返す。本文は送らず、ヘッダだけ送信する。
→ブラウザのキャッシュだけで出力し、ヘッダの一分の情報の更新にのみ帯域負荷をかけるので非常に速くなる
・CDNやプロキシキャッシュの効率化
画像・CSS・JSなどが更新されていなければ304を返し、帯域節約を行う。

ともかく、301 302 304を定義したことでリダイレクトの仕組みとキャッシュの効率化が

302、303 307に分かれる

さて時計の針を2年進めて1997年のRFC2068に進みましょう。
このタイミングでHTTPの一部を修正し、HTTP/1.1として整備されました。これによって今までのRFC1945で定義されたものをHTTP/1.0と呼ばれます。

この流れが生まれた背景として、302リクエストに関する曖昧性、いわゆる「302問題」への対処がモチベーションでした。
302問題というのは、本来302リクエストは「リソースが一時的に別の場所にあるから、そこへ同じリクエストを送れ」という意味でした。
つまり、もしクライアントが POST /submit を送ったら、サーバーが302を返して Location: /new-submit を指定した場合、本来は POSTのまま /new-submit に送るべきでした。

しかし90年代の主流ブラウザだったNetscapeやInternetExploreでは勝手に以下の挙動を示すようにしていました。

1 ユーザーがフォームを送信 → POST /submit を呼び出す
2 URLの一時的な変更のためサーバーが302を返す → Location: /new-submitを書き込み /new-submitに送るようにユーザーに依頼
3 ブラウザが 勝手に受け取ったPOSTをGETに変換 して GET /new-submit を呼び出す

となり、リクエスト内容が勝手に書き換わることが起こってしまいました。
なぜこのようなことをしたのでしょうか?これはシンプルにUXの都合でした。
例として、ネットショップで商品を買う場合を考えてみましょう。
ある商品を購入するために、URL①にPOSTリクエストを送ります。このとき、例えばこのPOSTリクエストには決済情報などが載っています。
このURLが一時的にURL②に変更されていたとします。このときもし仕様通り再びPOSTリクエストを送る仕様になっていれば、決済情報を再度URL②に送ることになり、あまり安全ではありません。2重決済などが起こる可能性が考えられます。
以上のような理由から、ブラウザは仕様に反して、勝手にPOSTリクエストの302は、GETリクエストに書き換えて送るようにしていました。

たしかにこのほうが便利で安全ですが、サーバー側は「POSTデータが渡される」と思っていたのに、実際は消えてしまい、サーバーにとっては嬉しくありません。また、ブラウザによってこの仕様がまちまちなのがあまりよろしくありませんでした。

そこで、新たに303コード See Other = 「POSTの後はGETで遷移せよ」と明示するコード、および307コードTemporary Redirect = 「POSTはPOSTのまま保持せよ」と明示するコードが追加されました。これにより、機能が分解され、どちらの手段をとるかについてブラウザに委ねられることなりました。

このとき305というのも導入されています。が現在非推奨となっているので知らなくてもいいでしょう。また307を定義したくせに306はやはり欠番です。この306は未だに何もつかわれておらず、欠番になっています。

、、、あれ?この問題って302だけじゃなく301でも起きるくないか?と思った方、そのとおりです。もう少し先で伏線回収が待っているのでしばしお待ちを。

安定の2000年代

というわけで悩みのタネだった302問題は解消し、安定の2000年代に入ります。
この頃になると、クライアントリダイレクトという技術と、短縮URLという技術が登場します。

クライアントリダイレクトとは

現在、リダイレクトは上記で見てきたように、サーバで行われることが多数です。誤ったリンクにURLリクエストを送ってしまった場合は散々見てきたように3xxリクエストを介して適当なURLへのリダイレクトを行いますが、この時期にはクライアント側でのリダイレクトのシステムが提案され、かなり流行りました。
具体的には、サーバによって3xx系リクエストを受け取るのではなく、200リクエストでHTMLそのものをGETし、そのHTML内にリダイレクトの指示が埋め込まれているという形式です。行き先そのものを教えてもらうのではなく、行き先を書いた紙をもらうようなイメージですね。
サーバーにリダイレクトの負荷がかからず、静的なホスティング環境で非常に重宝されたそうです。

例えば

<meta http-equiv="refresh" content="5;url=https://example.com/next">

だったら、GETリクエストでこのようなHTMLを取得することができるが、5秒後に次のURLへ飛ぶ、というような形です。

この時期にクライアントリダイレクトは流行ったものの、結局あまりメジャーになりませんでした。
というのも、リダイレクトしている感がないというか、「送り返されてまた送り直す」というユーザーインターフェースが利用者にとって混乱を与えないだろうという考えが主流になったことです。
現在ではこのような考えからクライアントベースのリダイレクターはメジャーではなく、サーバーベースのリダイレクターが使われています。

URLの短縮

この時代では長ったらしいURLを短くしようという流れが生まれました。よくツイッターの文字数制限に引っかからないようにURLを短くするアレですね。これも言われたらわかると思いますがリダイレクターの仕組みを使っています。
短縮したURLにリクエストを送ると、例えば301リクエストが返り「このURL XはURL Yに恒久的に変更されたので以降そちらに送るように」といったようなリダイレクターが裏側で動作します。
このサービスは現状も使われていますね。

HSTSの登場

さて皆さんに馴染み深いhttpとhttpsのリダイレクトの話です。
HTTPSは御存知の通り、盗聴されるリスクの高いHTTPにTLS/SSLの仕組みをラップしたプロトコルです。
このとき、まいどまいどHTTPで送られたリクエストに対してHTTPSにリダイレクトするようにサーバーから命令が来ます。
しかしながらこれを毎回やるのは非効率かつ、HTTPでのリクエストが送られるタイミングが存在することからも攻撃者に攻撃のスキを与えてしまい、あまり健全ではありません。
RFC6797が2012年に標準化され、これにより一度訪れたサイトは以後ずっとHTTPSで接続するような仕組みが導入されました。最初はGoogleがChromeで自主的に導入していたようです。やっぱGoogleかっけえ
HSTSの仕組みとしては、一度HTTPSで正しいアクセスがあった場合、サーバがクライアントブラウザに対して

Strict-Transport-Security: max-age=31536000; includeSubDomains

のように「このサイトは次回以降は必ずHTTPSでアクセスするように」という司令がサーバから下ります
この結果HTTPからHTTPSへの不必要なリダイレクトを削減するようになりました。

2014-2015 308の登場

このような形で進化、拡大していったリダイレクトの300台リクエストですが、ここにきて「恒久リダイレクト」が改定されました。
さて思い出してほしいのが、302問題です。ブラウザがリダイレクト時にPOSTリクエストをPOSTリクエストのままにせず、勝手にGETリクエストに変えてしまっており、これが既成事実化していることです。
この問題は当然301リクエストでもありました。リダイレクト先が一時的なものか恒久的なものかという違いですからね。
というわけで301リクエストに対しても、POSTリクエストをリダイレクトした場合にGETに切り替えるかPOSTに切り替えるかは完全に曖昧なままでした。302ではしっかり307を用意したのに、301の方は整備が遅れたのは、謎ですよね。

というわけでPOSTはPOSTのまま保持するものは308リクエスト、リクエストの保持を保障せずにリダイレクトするものは301リクエストとして棲み分けした標準化が実施されました。
というわけで301(恒久・POST→POST・GETどちらでも可)303(一時的・POST→GET)307(一時的・POST維持)308(恒久・POST維持)
の4つがしっかりfixされたわけですね

近年のトピック

近年はRFC9110で何も言及しなかった305リクエストが非推奨にすることが決まりました。
image.png
廃止を宣言されたお前は泣いていい。

せっかくなので305についても扱っておくと、305の意味は「このリソースにアクセスするには、指定されたプロキシを通せ」というものです。

HTTP/1.1 305 Use Proxy
Location: http://proxy.example.com:8080/

のようなかたちで、これを受けたクライアントは、以後のリクエストを Location ヘッダで指定されたプロキシ経由で送ることが想定されていました。

しかしながらヘッダをいじればプロキシ先を指定できるというところが問題視され、攻撃者が偽の305 User Proxyを差し込むとユーザの通信が攻撃者のプロキシを経由することになり非常に危険でした。
また305として君臨している割にバズっておらず、IEやChromeなどで対応されていませんでした。

これらの理由からプロキシをセットするのではなく、「リソースの場所が変わった」というかたちでプロキシの利用を代替する流れになりました。HSTSとリダイレクト番号301 302 303 307 308を駆使して、安全なプロキシのようなネットワークが整備できたわけですね。

以上が大まかな歴史になります!参考になったでしょうか!!(ちなみにこれが初投稿です!)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?