[2] [CODE(HTTP)[[[3xx]]]] [[応答]]で他の [[URL]] を指定し、[[利用者エージェント]]にその
[[URL]] に[[要求]]を送信することを求めること、あるいはそのような[[応答]]のことを、
[DFN[[RUBYB[[[リダイレクト]]]@en[redirect]]]]といいます。

[FIG(sequence)[
:C:[[利用者エージェント]]
:S:[[起源サーバー]]①
:S2:[[起源サーバー]]②
:C -> S:[[要求]]
:S -> C:[CODE(HTTP)[[[3xx]]]] [CODE(HTTP)@en[[[Location:]] [VAR[URL]]]]
:C -> S2:新 [VAR[URL]] に[[要求]]
:S2 -> C:[[応答]]
]FIG]

* 仕様書

[REFS[
- [306] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-08-07 05:54:02 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-6.4>
- [518] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-06-07 01:55:45 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-4.3.4>
- [534] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-08-07 05:54:02 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-7.1.2>
- [6] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-08-07 05:54:02 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#page-79>
- [9] [CITE@en[RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content]] ([TIME[2014-08-07 05:54:02 +09:00]] 版) <https://tools.ietf.org/html/rfc7231#section-9.5>
- [56] [CITE@en-US[Fetch Standard]] ([TIME[2015-07-07 18:54:30 +09:00]] 版) <https://fetch.spec.whatwg.org/#concept-http-fetch>
- [62] [CITE@en-US[Fetch Standard]] ([TIME[2015-08-19 15:28:45 +09:00]] 版) <https://fetch.spec.whatwg.org/#redirect-status>
- [67] [CITE@en[Referrer Policy]] ([TIME[2016-05-21 07:45:08 +09:00]]) <https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect>
]REFS]

* プロトコル

[305] [[HTTPリダイレクト]]は、次の[[プロトコル要素]]により構成されます。
[FIG(short list)[
- [[状態符号]] [CODE(HTTP)[[[3xx]]]]
-- [CODE(HTTP)[[[300]]]]
-- [DFN[[RUBYB[[[リダイレクト状態]]]@en[redirect status]]]] [SRC[>>62]]
--- [CODE(HTTP)[[[301]]]]
--- [CODE(HTTP)[[[302]]]]
--- [CODE(HTTP)[[[303]]]]
--- [CODE(HTTP)[[[307]]]]
--- [CODE(HTTP)[[[308]]]]
- [CODE(HTTP)@en[[[Location:]]]] [[ヘッダー]]
- [CODE(XMLe)@en[[[location]]]] [[要素]]
- [[HTTPリダイレクトfetch]]
]FIG]

;; [23] [[状態符号]]は多数ありますが、 [[Fetch Standard]] によって自動的な[[リダイレクト]]が行われることとされているのは[[リダイレクト状態]]に分類される
[CODE(HTTP)[[[301]]]], [CODE(HTTP)[[[302]]]], [CODE(HTTP)[[[303]]]],
[CODE(HTTP)[[[307]]]], [CODE(HTTP)[[[308]]]] の5種類だけです。

* 状態符号の選択

[33] [[著者]] ([[Webアプリケーション]]開発者) は、
[[リダイレクト]]で使うべき[[状態符号]]を次のように決定できます。
[FIG(steps)[
= [50] [[captive portal]] の場合
== [CODE(HTTP)[[[511]]]] を使うべきです ([[HTTPリダイレクト]]ではありません)。
= [34] 即座に遷移させずに、いったん何らかのメッセージを表示してから移動させたい場合
=- [40] [[HTTPリダイレクト]]では実現できないので、
[CODE(HTTP)@en[[[Refresh]]]] や [[JavaScript]] を使って[[クライアント側]]で[[リダイレクト]]する必要があります。
=- [49] [CODE(HTTP)[[[POST]]]] で新しい[[資源]]を作成した時は
[CODE(HTTP)[[[201]]]] を使えます ([[HTTPリダイレクト]]ではありません)。
= [52] 複数の移動先の候補がある場合
== [CODE(HTTP)[[[300]]]] と [[HTML]] による[[リンク]]で表現できます ([[HTTPリダイレクト]]ではありません)。
= [46] [[Webサイト]]の移転等で他の [[URL]] を見るべき場合
== [47] 同等の新しい [[URL]] がある場合
=== [59] [CODE(HTTP)@en[[[POST]]]] しようとしたなら[[リダイレクト]]先でも
[CODE(HTTP)@en[[[POST]]]] させたい場合
==== [CODE(HTTP)[[[308]]]]
=== [60] そうでもない場合
==== [CODE(HTTP)[[[301]]]]
== [48] そうでない場合 ([[トップページ]]への移動など)
=== [CODE(HTTP)[[[302]]]]
= [51] 不完全な [[URL]] から完全な [[URL]] に移動させたい場合 ([[ディレクトリー]]の末尾に [CODE[/]] がない場合など)
== [CODE(HTTP)[[[301]]]]
= [54] [[短縮URL]]から正規の [[URL]] への展開の場合
== [CODE(HTTP)[[[301]]]]
= [57] [CODE(HTTP)@en[[[POST]]]] しようとしたなら[[リダイレクト]]先でも
[CODE(HTTP)@en[[[POST]]]] させたい場合
== [CODE[[[307]]]]
= [45] その他の場合、例えば:
[FIG(list)[
- [CODE(HTTP)@en[[[POST]]]] の後次のページに移動させたい場合
- [[ログイン]]ページの類に移動させたい場合
- [[OAuth]] 認証フロー
- [[ガラケー]]など特定[[装置]]向けのページに移動させたい場合
- 特定[[言語]]版の [[URL]] に移動させたい場合
]FIG]
== [CODE(HTTP)[[[302]]]]
]FIG]

;; [76] [[Semantic Web]] [[信者]]でもなければ、 [CODE(HTTP)[303]]
が必要な場合は滅多にありません。

* 意味

[14] [[リダイレクト]]は、[[対象資源]]のかわりに、別の [[URL]]
にアクセスするべきであることを表しています。

[15] その実際の意味は様々です。
[FIG(list)[
- [16] [[Webサイト]]構成の都合その他の理由により [[URL]]
([[ドメイン]]や [[path]] など) が変化した時に、旧 [[URL]]
でのアクセスを新 [[URL]] に誘導するために利用するのが主たる利用法です。
[CODE(HTTP)[[[301]]]] が最適な[[状態符号]]ですが、 [CODE(HTTP)[[[302]]]]
となっていることも多々あります。
- [17] [[鯖]]側[[Webアプリケーション]]などで [CODE(HTTP)@en[[[POST]]]]
を処理した後に、処理が反映されているページやその他関連するページなど、
[CODE(HTTP)@en[[[POST]]]] 操作の完了後に[[利用者]]に提示するべきページに遷移させるためによく使われます。
[CODE(HTTP)[[[302]]]] がよく用いられます。
- [18] 存在しない [[URL]] にアクセスしたときに、 [CODE(HTTP)[[[404]]]]
のかわりにトップページなどに[[リダイレクト]]することがあります。
ただしこの動作は [[URL]] の打ち間違いでも遷移して[[アドレスバー]]が書き換わってしまうなど、
[[利用者]]には不評で最近はあまり使われなくなっています。
- [19] [[Cookie]] などによる閲覧制限が行われている場合に、
閲覧権限を持たない[[クライアント]]からのアクセスを[[トップページ]]や[[ログインページ]]などに[[リダイレクト]]することがあります。
本来は [CODE(HTTP)[[[401]]]] や [CODE(HTTP)[[[403]]]] や [CODE(HTTP)[[[404]]]] 
を使うべきなのでしょうが、[[利用者]]の便宜その他の理由でしばしば使われています。
- [26] [[OAuth]] のように[[リダイレクト]]を前提に構築された[[認証]]プロトコルも存在します。
- [20] [[captive portal]] で[[ログインページ]]に[[リダイレクト]]することがあります。
- [21] [[Semantic Web]] の世界では、[[資源]]の [[URL]] からその情報が含まれる
[[RDF]] ファイルへ [CODE(HTTP)[[[303]]]] [[リダイレクト]]を使うことになっています。
- [53] [[短縮URL]]を提供するために使われることがあります。
- [55] [[内容折衝]]の手段として使われることがあります。
]FIG]

* 処理

[539] 新旧の[[要求]]と[[応答]]は、互いに完全に独立したものです。 [[HTTP]]
プロトコルとしては状態は保持していません。新旧[[要求]]を異なる
[[HTTP接続]]を使って送信しても何ら問題ありませんし、
新旧[[要求]]の送信先の[[鯖]]がそもそも異なっているかもしれません。

* 相対 URL

[538] [CODE(HTTP)@en[[[Location:]]]] [[ヘッダー]]には[[相対URL]]
を指定することもできます。この値は[[実効要求URL]]を[[基底URL]]
として[[解決]]されます。

;; [CODE(HTTP)@en[[[Location:]]]] を参照。

* リダイレクトと要求メソッド

[11] [CODE(HTTP)[[[301]]]] と [CODE(HTTP)[[[302]]]] では、
[CODE(HTTP)@en[[[POST]]]] だった場合[[リダイレクト]]先では
[CODE(HTTP)@en[[[GET]]]] に書き換えます [SRC[>>56]]。それ以外の[[要求メソッド]]はそのまま保持します。

[12] [CODE(HTTP)[[[303]]]] では、[[リダイレクト]]先では
[CODE(HTTP)@en[[[GET]]]] に書き換えます [SRC[>>56]]。

[13] [CODE(HTTP)[[[307]]]] と [CODE(HTTP)[[[308]]]] では、
[[リダイレクト]]先でも[[リダイレクト]]前の[[要求メソッド]]をそのまま保持します。

[307] [[要求メソッド]]が[[安全]]でない場合、自動的な[[リダイレクト]]には注意する必要があります。
[[利用者]]は[[安全]]でない[[要求]]を[[リダイレクト]]してほしくないかもしれません。 [SRC[>>306]]

[308] [CODE(HTTP)@en[[[Location:]]]] があれば、
未対応の [CODE(HTTP)[[[3xx]]]] [[状態符号]]であっても、
自動的に[[リダイレクト]]して構いません [SRC[>>306]]。

[517] [[起源鯖]]は、 [CODE(HTTP)@en[[[PUT]]]] [[要求]]に対して[[対象資源]]の状態を変更せず、
他の[[資源]]に適用したい場合は、
適切な [CODE(HTTP)[[[3xx]]]] [[応答]]を送信し[['''なければなりません''']]。
その場合[[利用者エージェント]]は[[リダイレクト]]に従うか選ぶことができます。 [SRC[>>518]]

[DEL[
;; [22] 現状 [[Fetch Standard]] では[[リダイレクト]]前後の[[要求メソッド]]の変化を規定していません。 [TIME[2014-09-04T14:34:24.200Z]]
]DEL]

[98] 
[[HTTPクライアント]]によっては[[リダイレクト]]後の[[要求メソッド]]が
[[Webブラウザー]]と違った挙動になることがあります。
初期 [[HTTP]] 仕様の迷走と関係しているのですが、
[[クライアント]]によって動作が違うのは困ったものです。
新しい[[クライアント]]は [[Web互換性]]のために 
[[Webブラウザー]] ([CITE[[[Fetch Standard]]]]) と同じ動作を実装するべきです。
[SEE[ 互換性の問題の実例: [[GAS]] ]]

* リダイレクトとヘッダー

[7] [[リダイレクト]]前後で指定するべき[[ヘッダー]]の同一性や差異について特に規定はありません。

[8] [[RFC 7231]] は[[ヘッダー]]の仕様書に対し、[[リダイレクト]]前後で保持するべきか明記することを検討するよう求めています
[SRC[>>6]]。

* リダイレクトループ

[SEE[ [[リダイレクトループ]] ]]

* 素片識別子

[540] [[素片識別子]]が適切で無い場面もあるとして、
[CODE(HTTP)[[[201]]]] を例に挙げています [SRC[>>534]] が、
なぜか禁止はされていません。また [CODE(HTTP)[[[201]]]]
以外にも不適切な場面が存在することを暗示していますが、
実際に何が該当するのかは不明です。

[537] [[利用者エージェント]]は、[CODE(HTTP)[[[3xx]]]] [[応答]]の
[CODE(HTTP)@en[[[Location:]]]] に[[素片識別子]]が含まれていない場合、
[[要求対象]]を[[生成]]するのに使った[[URL]]の[[素片識別子]]を継承するものとして処理しなければ[['''なりません''']]
[SRC[>>534]]。

[41] <http://foo.example/bar#fragment1> を取り寄せる時に、次のようになったとします。

[PRE[
C: GET /bar HTTP/1.1
C: Host: foo.example
C: 
S: 302 Found HTTP/1.1
S: Location: http://foo.example/hoge
S: 
]PRE]

この時、 [[UA]] の望ましい動作は、 ([[WWWブラウザ]]であれば)
<http://foo.example/hoge> を要求し、その #fragment1 を表示することです。

[42] 同じ例で、次のような応答があったとしましょう。
[PRE[
S: 302 Found HTTP/1.1
S: Location: http://foo.example/hoge#fragment2
S: 
]PRE]

この時 WWW ブラウザは、 <http://foo.example/hoge#fragment2>
を表示し、 #fragment1 のことは忘れます。

[44] >>42 で、「アドレス・バー」のような [[UI]] 部分をどうするかという問題がありますね。
[[301]] なら新しい (#fragment2 の) URI にしてしまえばいいですが、 [[307]]
の時はどうなんでしょう。元の #fragment1 にしておくのと、 #fragment*
は削ってしまうのと2種類考えられますが。

[43] 但し実際には、この #fragment の扱いについては仕様・実装がぐちゃぐちゃです。
できることならば [CODE[Location]] 欄で素片識別子を使わないといけないようなことにならないようによく考えておくべきでしょう。[WEAK[それでも使わざるを得なくなったときは仕方ないですし、 UA の挙動なんて飾りです、偉い人には分からなくて結構と開き直るのも場合によってはありでしょう。]]


** 仕様書の類の言及

[24] >>20,>>5 [[RFC2396]] ([[URI]]) によると [CODE(ABNF)[absoluteURI]] は [CODE(ABNF)[fragment]] を含みません。従って [[HTTP/1.1]] と CGI で仕様が不整合な気がします。

実際のところ [CODE[fragment]] つき URI を送っても多くの URI は解釈する気がしますが、仕様的には無理ということでいいですか?

[35] >>24 ''HTTP/1.1 Specification Errata'' [DEL[<http://world.std.com/~lawrence/http_errata.html#location-fragments>]] [INS[<http://purl.org/NET/http-errata#location-fragments>]]
に載ってました。 (こんなの知らなかった。) >>6 
の通り、 '''HTTP でも URI の後に #fragment をつけることが出来ます'''。

[36] とはいえ、知らない実装者も居るだろうな。。。要注意ですね。

[37] >>35 の文書から、該当部分の注記。

[FIG(quote)[
> There are circumstances in which a fragment identifier in a Location URL would not be appropriate:
- With a 201 Created response, because in this usage the Location header specifies the URL for the entire created resource.
- With a 300 Multiple Choices, since the choice decision is intended to be made on resource characteristics and not fragment characteristics.
- With 305 Use Proxy. 

> At present, the behavior in the case where there was a fragment with the original URI, e.g.: http://host1.example.com/resource1#fragment1 where /resource1 redirects to http://host2.example.com/resource2#fragment2 is 'fragment1' discarded? Do you find fragment2 and then find fragment1 within it? We don't have fragment combination rules.

[CODE[Location]] URL 中での素片識別子が適切でない場面があります。
- [[201]] Created (作成しますた) 応答。 [CODE[Location]]
頭を使用して作成された資源全体を URL を指定するものだから。
- [[300]] Multiple Choices (複数選択肢)。選択決定は資源の性質についてなされるもので素片の性質についてではないから。
- [[305]] Use Proxy (串使って)。

現在、元の URI に素片がある場合、例えば 
<http://host1.example.com/resource1#fragment1> で [SAMP[/resource1]]
が <http://host2.example.com/resource2#fragment2>
に redirect している時に「fragment1」は捨てられているのでしょうか?
[SAMP[fragment2]] を探してそれから [SAMP[fragment2]] を探すのでしょうか?
我々は素片組み合わせ規則は持っていません。
]FIG]

[38] >>37 の後半の問題、実際のところどうなんだろう?
どっちにしる!とも言いがたいよなあ。

[39] ''Common User Agent Problems: Handle the fragment identifier of a URI when the HTTP request is redirected.'' <http://www.w3.org/TR/cuap#cp-fragment>

この [[W3C]] [[NOTE]] は、 #fragment に対応していない UA
があるけどちゃんとしる! と言うと共に、 >>37-38 問題について、 #fragment2 
にしる! と言っています (小文字 must)。

[310] [CITE@en[Web Applications 1.0 r6322     Make Facebook work. See http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx]]
( ([TIME[2011-07-24 11:28:00 +09:00]] 版))
<http://html5.org/tools/web-apps-tracker?from=6321&to=6322>

[311] [CITE@en[URL Fragments and Redirects - EricLaw's IEInternals - Site Home - MSDN Blogs]]
( ([TIME[2011-07-24 12:07:00 +09:00]] 版))
<http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx>

[312] [CITE@en[[[draft-bos-http-redirect-00]] - Handling of fragment identifiers in redirected URLs]]
([TIME[2011-08-17 18:10:19 +09:00]] 版)
<http://tools.ietf.org/html/draft-bos-http-redirect-00>

[10] [[RFC 7231]] は、[[リダイレクト]]によって元の [[URL]]
に指定されていた[[素片識別子]]をリダイレクト先の [[URL]]
の[[文書]]が読み取れることによる情報漏洩の危険があることを指摘しています [SRC[>>9]]。

** 実装について

[58]
[[WinIE 6.0]] (もしかしたら以前の版も。) は redirect された時の [CODE(HTTP)[Location]] URI 参照に素片識別子がついていると直後の再要求時にその素片識別子ごと [CODE(ABNF)[Request-URI]] にして送ってしまうみたいです。
([[名無しさん]] [WEAK[2004-05-03 04:37:14 +00:00]])


* HTTP 以外の URL

@@ ...

* リダイレクトの開始

[543] [[HTTPリダイレクト]]は、[[応答]]の直後に[[リダイレクト]]後の[[要求]]が送信されることを期待しています。

[544] 仕様上は[[応答]]から[[要求]]までの待ち時間を [CODE(HTTP)@en[[[Retry-After:]]]]
[[ヘッダー]]で指定できることになっていますが、実装されていませんし、
今後実装される見込みもなさそうです。

[545] 一旦何らかのページを表示して、すこし待ってから別のページを表示したいときは、
[CODE(HTML)@en[[[Refresh]]]] を利用できます。

[309] [[WinIE8]]、[[Opera]]、[[Chrome]]、[[Firefox]] のどの [[Webブラウザー]]も、
[[リダイレクト]]している [[HTTPメッセージ]]全体が到着するのを待たず、
[[頭部]]を受け取り次第すぐに[[リダイレクト]]先の [[URL]]
の取得をはじめるようです。

;; <http://suika.fam.cx/~wakaba/-temp/test/http/redirect/delayed.cgi> ([[頭部]]はすぐに返すものの、[[応答本体]]の生成が終わるまで100秒かかる例)。

;; [CODE(HTTP)@en[[[Location:]]]] [[頭欄]]を受け取り次第すぐに次に進むのか、
[[頭部]]をすべて受け取り終わるまで進まないのかは未検証です。

* セキュリティー

[FIG(short list)[
- [25] [[開放型リダイレクト器]]
]FIG]

* 参照元

[68] [DFN[Set [VAR[request]]’s referrer policy on redirect]] は、
[VAR[要求]]と[VAR[応答]]について次のようにします [SRC[>>67]]。
[FIG(steps)[
= [69] [VAR[方針]]を、[VAR[応答]]に
[[Parse a referrer policy from a [CODE[Referrer-Policy]] header]]
を適用した結果に設定します。
= [70] [VAR[方針]]が[[空文字列]]でなければ、
== [71] [VAR[要求]]の[F[参照元ポリシー]]を、[VAR[方針]]に設定します。
]FIG]

;; [74] これは [[HTTPリダイレクトfetch]] から呼び出されます。

* 利用者インターフェイス

[78] [[アドレスバー]]も参照。

* 実装

[100] [CITE@ja[まきのっぴさんはTwitterを使っています: 「そこで「それリダイレクト設定どこに書きました? .htaccessに書いてない? でしょ? じゃあhttpd.confに書いて再検証してみて」と指示してやり直した結果、許容し得る性能低下で済むようになったとの報告があり、数万行のリダイレクト設定を施したリニューアルが無事実現できました。」 / Twitter]], [TIME[12時間][2023-04-03T16:40:25.000Z]], [TIME[2023-04-04T04:56:37.000Z]] <https://twitter.com/pmakino/status/1642930069403484160>

[99] [CITE@ja[tecklさんはTwitterを使っています: 「ちなみにNginxでリダイレクトさせた時は、起動時にメモリを食うものの速度自体は普通に高速でした。 その後リダイレクト件数が200万件?を超えてきてメモリも厳しくなったので Nginx + Go + SQLiteの動的リダイレクトに切り替えたら超省メモリになりました(便乗宣伝) https://t.co/PCPSVmJNBo」 / Twitter]], [TIME[3時間][2023-04-04T03:40:20.000Z]], [TIME[2023-04-04T06:45:51.000Z]] <https://twitter.com/teckl/status/1643101178165878784>


* 歴史

[519] [[リダイレクト]]には、元々の[[要求]]の[[要求対象]]を書き換え、
[[要求メソッド]]を維持するパターンと、[[要求メソッド]]を [CODE(HTTP)@en[[[GET]]]]
に書き換えるパターンがあります。

[520] [[HTTP]] 仕様書の著者の意図は、 [CODE(HTTP)[[[301]]]] と [CODE(HTTP)[[[302]]]]
は前者とするものでしたが ([[CERN]] の実装もそうなっていました)、 
実際には [CODE(HTTP)[[[303]]]] 共々後者の動作とする実装があり、
やがて後者に収束していきました。 [SRC[>>306]]

[521] このため後者の意味の [CODE(HTTP)[[[307]]]] が新たに追加されました。
更に、[[要求メソッド]]が [CODE(HTTP)[[[POST]]]] だった場合のみ、
[CODE(HTTP)[[[301]]]] と [CODE(HTTP)[[[302]]]] で前者の動作でも[[適合]]することとされました。
[SRC[>>306]]

;; [522] [[HTTP]] の仕様書の著者の意図としては、依然として [CODE(HTTP)[[[301]]]]
と [CODE(HTTP)[[[302]]]] は元の[[要求メソッド]]のまま[[リダイレクト]]するのが正しい使い方のようです。
15年以上にわたり安定している現在の慣習と互換性のない“理論上は正しい”
方式にこだわり続ける意図が何なのかは謎です。 [[Webブラウザー]]も[[鯖]]側の
[[Webアプリケーション]]も、 [CODE(HTTP)[[[301]]]] や [CODE(HTTP)[[[302]]]]
で[[要求メソッド]]が保持されることなど想定しておらず、
そうでない実装方法は決して[[Web互換]]では無いのですが・・・。

[1] [CITE@ja[リダイレクトの設定とインデックスに登録されるURL - インフォセンター - Yahoo!検索]]
([TIME[2010-05-25 10:35:59 +09:00]] 版)
<http://info.search.yahoo.co.jp/archives/002865.php>

* 関連

[3] 通常は [[HTTPリダイレクト]]とは呼びませんが、 [CODE(HTTP)@en[[[Refresh:]]]]
[[ヘッダー]] (や [CODE(HTML)@en[[[<meta http-equiv=refresh>]]]])、
[[HSTS]] も[[リダイレクト]]を実現するものです。

[4] また[[リダイレクト]]には [[JavaScript]] によって[[クライアント]]側で実行する手法もあります。

[5] [[HTTP]] の仕様書は、 [CODE(HTTP)[[[300]]]] や [CODE(HTTP)[[[304]]]]
も[[リダイレクト]]と呼んでいます。

;; [CODE(HTTP)[[[3xx]]]] の項を参照。

[542] [CODE(HTTP)[[[201]]]] でも [CODE(HTTP)@en[[[Location:]]]]
を使いますが、本項の[[HTTPリダイレクト]]とは異なります。

[541] [[HTTP]] には他に [CODE(HTTP)@en[[[Content-Location:]]]] や
[CODE(HTTP)@en[[[Link:]]]] もありますが、本項の [[HTTPリダイレクト]]とは異なります。

[526] [[CGI]] には[[局所リダイレクト応答]]と[[クライアントリダイレクト応答]]がありますが、
[[クライアントリダイレクト応答]]が[[HTTP応答]]における[[リダイレクト]]に相当します。

[27] [[Referrer]] によって[[リンク元]]が送信されてしまうことを防ぐため、
本来の[[リンク先]]との中間に1ステップ挟む“中間ページ”型リンクも、
広義の[[リダイレクト]]と言えます。 [CODE(HTTP)@en[[[Refresh]]]] や
[CODE(JS)@en[[[location.href]]]] と併用することで中間ページを設けつつ自動で[[リンク先]]に遷移させる本当の[[リダイレクト]]になっている場合もあります。

[28] [[ガラケー]]のような[[リダイレクト]]回数の制限の厳しい[[利用者エージェント]]との互換性のため、
敢えて[[HTTPリダイレクト]]を使わずに >>27 のような中間ページを使うこともあります。

* メモ

[527] [CITE[Response.redirect() > new RedirectResponse() · a083a27 · whatwg/fetch]]
( ([TIME[2014-06-04 07:55:35 +09:00]] 版))
<https://github.com/whatwg/fetch/commit/a083a27c53a65e5ba93c486401fb55c2a68a7cd3>


[528] [CITE@en[HTTP - WHATWG Wiki]]
( ([TIME[2014-08-05 06:24:41 +09:00]] 版))
<http://wiki.whatwg.org/wiki/HTTP#Redirects>

[529] [CITE@en[HTTP Methods and Redirect Status Codes - IEInternals - Site Home - MSDN Blogs]]
( ([TIME[2014-08-25 14:22:36 +09:00]] 版))
<http://blogs.msdn.com/b/ieinternals/archive/2011/08/19/understanding-the-impact-of-redirect-response-status-codes-on-http-methods-like-head-get-post-and-delete.aspx>

[530] [CITE@en[598304 – XHR rewrites non-POST methods upon 301/302 redirects]]
( ([TIME[2014-08-25 14:27:20 +09:00]] 版))
<https://bugzilla.mozilla.org/show_bug.cgi?id=598304>

[531] [CITE@en[676059 – Make redirect prompting depend on HTTP-safeness of method, not presence of request body]]
( ([TIME[2014-08-25 14:28:27 +09:00]] 版))
<https://bugzilla.mozilla.org/show_bug.cgi?id=676059>

[532] [CITE[Test Cases for HTTP Redirects]]
( ([TIME[2014-07-27 13:47:16 +09:00]] 版))
<http://greenbytes.de/tech/tc/httpredirects/>

[533] [CITE[Bug 60440 – ''''''[''''''Qt'''''']'''''' Redirection of HTTP POST (3xx) incorrectly includes original POST data]]
( ([TIME[2014-08-25 14:34:12 +09:00]] 版))
<https://bugs.webkit.org/show_bug.cgi?id=60440>

[330] [[au]] の[[ガラケー]]だと[[素片識別子]]が入っていると [CODE(HTTP)@en[[[404]]]] になります。

[406] [CITE[Location: javascript:alert(1) が返ってきた時のブラウザの動作 - Qiita ''''''[''''''キータ'''''']'''''']]
( ([TIME[2013-10-31 03:05:25 +09:00]] 版))
<http://qiita.com/ooooooo_q/items/1f0c2c64413495c46e6b>

[410] [CITE@en[HTTP - WHATWG Wiki]]
( ([TIME[2013-12-19 01:12:07 +09:00]] 版))
<http://wiki.whatwg.org/wiki/HTTP#Location_header>

[423] [CITE@en[URL Fragments and Redirects - IEInternals - Site Home - MSDN Blogs]]
( ([TIME[2014-08-31 15:42:14 +09:00]] 版))
<http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx>

[29] [CITE@en[Refactor manual redirect flag into redirect mode. Preparation for https:... · whatwg/fetch@8398149]]
([TIME[2015-03-29 17:15:41 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/83981498175633510878ebf97077ec632ceedc29>

[30] [CITE@en[Provide limited control over redirects. Fixes https://www.w3.org/Bugs/Pu... · whatwg/fetch@b6b4f87]]
([TIME[2015-03-29 17:17:23 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/b6b4f87048020cda6237ca4af02df62d43f99765>

[31] [CITE@en[598304 – XHR rewrites non-POST methods upon 301/302 redirects]]
([TIME[2015-04-08 18:29:56 +09:00]] 版)
<https://bugzilla.mozilla.org/show_bug.cgi?id=598304>

[32] [CITE@en[Certain redirects rewrite the request method. Fixes #32 · whatwg/fetch@a8e07c8]]
([TIME[2015-04-09 23:45:54 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/a8e07c886198e85ca3eb757f3ef284193da11a0f>

[61] [CITE@en[Put redirect statuses in a shorthand. · whatwg/fetch@bd284d1]]
([TIME[2015-08-20 13:04:49 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/bd284d112e207c900c61d90c8bd005a4b6e1d687>

[63] [CITE@ja[POSTリクエストをリダイレクトするとGETされる?POSTされる? - はこべブログ ♨]]
([TIME[2015-11-09 00:37:19 +09:00]] 版)
<http://hakobe932.hatenablog.com/entry/20090707/1246985195>

[64] [CITE@en[Fix #187: set body to null when method is set to `GET` in a redirect · whatwg/fetch@379daf2]]
([TIME[2016-01-05 10:52:52 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/379daf2b451b026f5fe2012da2f6e01ceccb3b58>

[65] [CITE@en[Revert #111: allow redirects to data URLs · whatwg/fetch@31f65e4]]
([TIME[2016-01-09 12:01:07 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/31f65e4625eacb3a74b5d1eba905d0600040c6ce>

[66] [CITE@en[Allow user agents to transmit RST_STREAM upon seeing a redirect · whatwg/fetch@af0dc92]]
([TIME[2016-03-26 11:55:47 +09:00]] 版)
<https://github.com/whatwg/fetch/commit/af0dc923f7636751996a9762309904511725a1a7>

[72] [CITE@en[Non-HTTP(S) schemes are a network error during redirects]]
( ([[annevk]]著, [TIME[2016-05-30 22:19:04 +09:00]]))
<https://github.com/whatwg/fetch/commit/9b75908a1e6f6f520a77b8b420015a61fb5d8512>

[73] [CITE@en[Navigate: remove "gone async" and define redirect handling]]
([[annevk]]著, [TIME[2016-07-04 17:38:20 +09:00]])
<https://github.com/whatwg/html/commit/8b630f5e4fa2ec8b0999470d09490bffe6e9a1e3>

[75] [CITE@en[Call out to Referrer Policy to set policy on redirect]]
([[estark37]]著, [TIME[2016-07-16 02:22:13 +09:00]])
<https://github.com/whatwg/fetch/commit/a8f1cd5ae2d080ee4e1e8e02b68e8ec6ae2c2833>

[FIG(quote)[
[FIGCAPTION[
[77] [CITE[Release Notes for Safari Technology Preview 17 | WebKit]]
( ([TIME[2016-11-10 10:08:39 +09:00]]))
<https://webkit.org/blog/7071/release-notes-for-safari-technology-preview-17/>
]FIGCAPTION]

> Ensured the redirection count is no more than 20 in case of cross origin requests (r208046)
> Ensured redirections are upgraded only if declared by CSP policy (r207752)
> 

]FIG]


[FIG(quote)[
[FIGCAPTION[
[79] [CITE@en[Webmention]]
([TIME[2017-01-11 04:06:01 +09:00]])
<https://webmention.net/draft/#h-limits-on-get-requests>
]FIGCAPTION]

> Receivers should place limits on the number of HTTP redirects they follow, for example limiting the number to 20, in order to prevent being stuck in a redirect loop if the sender continues to send redirects.

]FIG]


[80] [CITE@en[Do not always set the recursive flag in HTTP-redirect fetch]]
([[annevk]]著, [TIME[2017-03-07 22:56:45 +09:00]])
<https://github.com/whatwg/fetch/commit/869ec2c2224200988bbc604f7f5181b6bb9df2c3>

[81] [CITE@en[RFC 5323 - Web Distributed Authoring and Versioning (WebDAV) SEARCH]]
([TIME[2017-10-01 13:49:21 +09:00]])
<https://tools.ietf.org/html/rfc5323#section-5.4>

[82] [CITE@en[More eargerly send RST_STREAM on redirects]]
([[annevk]]著, [TIME[2017-11-24 20:11:46 +09:00]])
<https://github.com/whatwg/fetch/commit/fd286755e9664d570260c16f7c1933f424d2f39a>

[83] [CITE@en[Clarify semantics of checking done, closed, etc. states of a null body stream · Issue #635 · whatwg/fetch]]
([TIME[2017-11-30 23:31:25 +09:00]])
<https://github.com/whatwg/fetch/issues/635>

[84] [CITE@en[More eargerly send RST_STREAM on redirects by annevk · Pull Request #638 · whatwg/fetch]]
([TIME[2017-11-30 23:34:06 +09:00]])
<https://github.com/whatwg/fetch/pull/638>

[FIG(quote)[
[FIGCAPTION[
[85] [CITE@ja[ads.txt で認定販売者を宣言する - DoubleClick for Publishers ヘルプ]]
([TIME[2017-12-03 19:23:54 +09:00]])
<https://support.google.com/dfp_premium/answer/7441288?hl=ja>
]FIGCAPTION]

> ads.txt v1.0.1 への仕様更新に伴い、Google では元のルートドメイン外への単一の HTTP リダイレクトがサポートされるようになります(例: example1.com/ads.txt から example2.com/ads.txt へのリダイレクト)。
> 元のルートドメイン内であれば、複数のリダイレクトもサポートされます。

]FIG]


[86] [CITE@en[Response.redirect() results in status message still being OK? · Issue #664 · whatwg/fetch]]
([TIME[2018-04-25 11:02:34 +09:00]])
<https://github.com/whatwg/fetch/issues/664>

[87] [CITE@en["no-cors" POST and 307/308 redirects · Issue #593 · whatwg/fetch]]
([TIME[2018-06-01 01:01:06 +09:00]])
<https://github.com/whatwg/fetch/issues/593>

[88] [CITE@en[Avoid using the CORS flag to reset request's origin in redirects by annevk · Pull Request #594 · whatwg/fetch]]
([TIME[2018-06-01 01:01:51 +09:00]])
<https://github.com/whatwg/fetch/pull/594>

[89] [CITE@en[Preserve HEAD method on 303 redirect]]
([[annevk]]著, [TIME[2018-08-17 23:27:58 +09:00]])
<https://github.com/whatwg/fetch/commit/6f29b764cc57aaf2f431e15a3f0fec029926e9e0>

[90] [CITE@en[303 redirects should preserve HEAD · Issue #753 · whatwg/fetch]]
([TIME[2018-08-23 18:51:36 +09:00]])
<https://github.com/whatwg/fetch/issues/753>

[91] [CITE@en[Preserve HEAD method on 303 redirect by annevk · Pull Request #796 · whatwg/fetch]]
([TIME[2018-08-23 18:52:45 +09:00]])
<https://github.com/whatwg/fetch/pull/796>

[92] [CITE@en[Added a note about fetch redirects being covered by andypaicu · Pull Request #359 · w3c/webappsec-csp]]
([TIME[2019-03-08 12:27:53 +09:00]])
<https://github.com/w3c/webappsec-csp/pull/359>

[93] [CITE@en[Note somewhere that redirects are covered by fetch directives. · Issue #72 · w3c/webappsec-csp]]
([TIME[2019-03-08 12:28:05 +09:00]])
<https://github.com/w3c/webappsec-csp/issues/72>

[94] [CITE@en[Take tainted origin flag into account for the same origin check]]
([[annevk]]著, [TIME[2018-11-20 18:09:39 +09:00]])
<https://github.com/whatwg/fetch/commit/986618a62b2d7d31f93177ed178f0cb21b570d85>

[95] [CITE@en[fetch() "no-cors": cross-origin to same-origin redirect taints response · Issue #737 · whatwg/fetch]]
([TIME[2019-04-19 14:43:02 +09:00]])
<https://github.com/whatwg/fetch/issues/737>

[96] [CITE@en[Request's tainted origin flag fallout · Issue #756 · whatwg/fetch]]
([TIME[2019-04-19 14:43:21 +09:00]])
<https://github.com/whatwg/fetch/issues/756>

[97] [CITE@en[Take tainted origin flag into account for the same origin check by annevk · Pull Request #834 · whatwg/fetch]]
([TIME[2019-04-19 14:43:52 +09:00]])
<https://github.com/whatwg/fetch/pull/834>

[101] 
[CITE@en[RFC 4437: Web Distributed Authoring and Versioning (WebDAV) Redirect Reference Resources]], [TIME[2023-12-02T08:22:44.000Z]], [TIME[2023-12-02T08:34:29.349Z]] <https://www.rfc-editor.org/rfc/rfc4437.html>


- [102] 
[CITE@en[Delete request-body-headers for redirects altering the request method]], [[JuniorHsu]], [TIME[2019-12-12 01:52:11 +09:00]], [TIME[2023-12-03T06:09:25.000Z]] <https://github.com/whatwg/fetch/commit/20ec6d0552bae67ed19b50caecf9f88cdaed2a22>
- [103] 
[CITE@en[Test if we correctly strip request-body-headers for redirects by JuniorHsu · Pull Request #20596 · web-platform-tests/wpt · GitHub]], [TIME[2023-12-03T06:09:38.000Z]] <https://github.com/web-platform-tests/wpt/pull/20596>
- [104] 
[CITE@en[Should Content-Type header be stripped when redirecting from POST to GET? · Issue #609 · whatwg/fetch · GitHub]], [TIME[2023-12-03T06:10:05.000Z]] <https://github.com/whatwg/fetch/issues/609>
- [105] 
[CITE@en[765898 - XHR preserves Content-Type on cross-origin 303 redirect - chromium]], [TIME[2023-12-03T06:12:47.000Z]] <https://bugs.chromium.org/p/chromium/issues/detail?id=765898>
- [106] [CITE@en[Where in the spec is the content-type header filtered out on 301/302/303 redirects? · Issue #192 · whatwg/xhr · GitHub]], [TIME[2023-12-03T06:13:08.000Z]] <https://github.com/whatwg/xhr/issues/192>
- [107] 
[CITE@en[strip request-body-header for redireting from POST to GET by JuniorHsu · Pull Request #977 · whatwg/fetch · GitHub]], [TIME[2023-12-03T06:13:28.000Z]] <https://github.com/whatwg/fetch/pull/977>











