/
64.txt
538 lines (406 loc) · 29.3 KB
/
64.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
[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]
* リダイレクトとヘッダー
[7] [[リダイレクト]]前後で指定するべき[[ヘッダー]]の同一性や差異について特に規定はありません。
[8] [[RFC 7231]] は[[ヘッダー]]の仕様書に対し、[[リダイレクト]]前後で保持するべきか明記することを検討するよう求めています
[SRC[>>6]]。
* リダイレクトループ
[535] [[鯖]]は、[[リダイレクト]]先として[[リダイレクト]]を返す [[URL]]
を指定しても構いません。
[536] [[利用者エージェント]]は[[リダイレクト]]により[[要求]]を改めて送信した結果が[[リダイレクト]]の場合も、
更にその[[リダイレクト]]に従うことが期待されています。
[523] [[クライアント]]は、[[リダイレクト]]の循環を検出して対処する[['''べきです''']]
[SRC[>>518]]。
;; [524] なぜ [['''MUST''']] でなく [['''SHOULD''']] なのか謎です。
無限[[リダイレクト]]で[[無限ループ]]するような[[クライアント]]はどう考えてもバグっており、
有害でしかありません。
;; [525] [[RFC 2068]] は最大5回までとしており、注意が必要 [SRC[>>518]] です。
* 素片識別子
[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] [[アドレスバー]]も参照。
* 歴史
[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>