[27] [DFN[[CODE(HTTP)@en[[[Forwarded:]]]]]] [[ヘッダー]]は、
[[要求]]を[[串]]によって[[転送]]した際の情報を表すものです。

* 仕様書

[REFS[
- [8] '''[CITE@en[RFC 7239 - Forwarded HTTP Extension]] ([TIME[2014-09-07 05:21:07 +09:00]] 版) <https://tools.ietf.org/html/rfc7239>'''
-- [29] [CITE@en[RFC 7239 - Forwarded HTTP Extension]] ([TIME[2014-09-07 05:21:07 +09:00]] 版) <https://tools.ietf.org/html/rfc7239#section-5.5>
-- [32] [CITE@en[RFC 7239 - Forwarded HTTP Extension]] ([TIME[2014-09-07 05:21:07 +09:00]] 版) <https://tools.ietf.org/html/rfc7239#section-7.3>
-- [36] [CITE@en[RFC 7239 - Forwarded HTTP Extension]] ([TIME[2014-09-07 05:21:07 +09:00]] 版) <https://tools.ietf.org/html/rfc7239#section-7.4>
- [40] [CITE[Hypertext Transfer Protocol (HTTP) Parameters]] ([TIME[2014-06-13 18:52:05 +09:00]] 版) <http://www.iana.org/assignments/http-parameters/http-parameters.xhtml#forwarded>
]REFS]

* 意味

[10] [CODE(HTTP)@en[[[Forwarded:]]]] [[ヘッダー]]は、
[[要求]]の経路上で[[串]]が関わった際に書き換えられたり失われたりした情報を明かすものです
[SRC[>>8]]。

[16] ただしこの[[ヘッダー]]を追加することは必須の要件とはされていません。
[[串]]を通過した[[要求]]でもこの[[ヘッダー]]が無いかもしれませんし、
この[[ヘッダー]]があったとしてもすべての[[串]]が示されているとは限りません。

* 構文

[15] [CODE(HTTP)@en[[[Forwarded:]]]] [[ヘッダー]]の値は、
1つ以上の要素の[[リスト]] ([CODE(HTTP)[#]]) です [SRC[>>8]]。
[[リスト]]内の各要素は[[要求]]を処理した順序を表しており、
最初の要素が最初に[[要求]]を処理した ([CODE(HTTP)@en[[[Forwarded:]]]]
を送信するよう設定されている) [[串]]、最後の要素が最後に[[要求]]を処理した[[串]]です
[SRC[>>8]]。

[FIG(railroad)[
= 要素
= *
== [[OWS]]
== [CODE(HTTP)[[[,]]]]
== [[OWS]]
== 要素
]FIG]

[18] 各要素は [CODE(HTTP)[[[;]]]] 区切りの0個以上の項目 ([[引数]]) のリストです [SRC[>>8]]。

[FIG(railroad)[
= ?
== [[引数]]
= *
== [CODE(HTTP)[[[;]]]]
== ?
=== [[引数]]
]FIG]

;; [24] [CODE(HTTP)[[[;]]]] の前後に[[空白]]は認められていないようです。

[21] [[引数]]は名前と値を [CODE(HTTP)[[[=]]]] で連結したものまたは[[空文字列]]です。 [SRC[>>8]]

[19] [[引数]]の名前は[[字句]]で、[[大文字・小文字不区別]]です [SRC[>>8]]。

[20] [[引数]]の値は[[字句]]または[[引用文字列]]です [SRC[>>8]]。

[FIG(railroad)[
= [[字句]]
= [CODE(HTTP)[[[=]]]]
= |
== [[字句]]
== [[引用文字列]]
]FIG]

;; [23] [CODE(HTTP)[[[=]]]] の前後に [[BWS]] は認められていないようです。

[22] ある要素中に同名の[[引数]]を複数指定しては[['''なりません''']] [SRC[>>8]]。

* 引数

[28] 次の[[引数]]があります。

[FIG(short list)[
- [CODE(HTTP)@en[[[by]]]]
- [CODE(HTTP)@en[[[for]]]]
- [CODE(HTTP)@en[[[host]]]]
- [CODE(HTTP)@en[[[proto]]]]
]FIG]

[41] [[引数]]の [[IANA登録簿]] [SRC[>>40]] もあります。

[30] [[引数]]は [[IANA]] に登録する[['''べきです''']]。広く使われるであろうものは標準化する[['''べきです''']]。 [SRC[>>29]]

* 文脈

[13] この[[ヘッダー]]は通常の[[串]]でも[[逆串]]でも使えます [SRC[>>8]]。

[11] この[[ヘッダー]]は繊細なデータを伝えるものですから、
[[既定]]では無効とする[RUBYB[べき]@en[should]]です。また各[[引数]]はそれぞれ個別に設定できる[RUBYB[べき]@en[should]]です。 [SRC[>>8]]

;; [12] この[[ヘッダー]]は[[応答]]では使いません [SRC[>>8]]。

[17] この[[ヘッダー]]は複数指定できます。

* 処理モデル

[26] [[串]]は、新しい [CODE(HTTP)@en[[[Forwarded:]]]] [[ヘッダー]]を[[ヘッダー部]]の末尾に付け加えることもできますし、
既存の [CODE(HTTP)@en[[[Forwarded:]]]] [[ヘッダー]]の末尾に [CODE(HTTP)[[[,]]]]
と共に付け加えることもできます [SRC[>>8]]。

[14] [[串]]は既存の [CODE(HTTP)@en[[[Forwarded:]]]] [[ヘッダー]]を削除することもできます
[SRC[>>8]]。

* 歴史

** [CODE(HTTP)@en[Forwarded:]] ヘッダー (90年代)

[2] [CODE(HTTP)@en[[[Forwarded:]]]] は初期の [[HTTP]] 仕様案において[[電子メール]]の
[CODE(822)@en[[[Received:]]]] [[ヘッダー]]に近い形で定義されていました [SRC[>>7]]。
一時は実装されていましたが (>>3, >>1)、機能を削って [CODE(HTTP)@en[[[Via:]]]]
に置き換えられました [SRC[>>6]]。

[REFS[
- [7] [CITE@en[draft-ietf-http-v10-spec-01 - Hypertext Transfer Protocol -- HTTP/1.0]] ([TIME[2014-10-16 14:16:45 +09:00]] 版) <http://tools.ietf.org/html/draft-ietf-http-v10-spec-01#section-8.14>
- [6] [CITE[HTTP-wg Archive: Via Header Field (replaces Forwarded)]] ([TIME[2014-10-22 11:26:06 +09:00]] 版) <http://www.hpl.hp.com/personal/ange/archives/archives-96/http-wg-archive/0725.html>
]REFS]

[FIG(quote)[
[FIGCAPTION[
[3] ''Nonstandard HTTP Headers'' <http://web.archive.org/web/20020610043404/http://www.dais.is.tohoku.ac.jp/~kabe/WWW/nonstdhdr.html#Forwarded>
]FIGCAPTION]

>Forwarded: by proxy-URI [(product)] [for client-FQDN]
>draft-ietf-http-v10-spec-01.txt および draft-ietf-http-v11-spec-01.txt までの HTTP-draft に出現。 標準化に際しては 「冗長である」 という理由から Via: に置き換わっています。 "for ..." 部分は Via: から削られたため、Squid では代わりに X-Forwarded-For ヘッダを新設しました。 (当時まじめにDraft等を追っかけていたのは Squid くらいだったような気が)
]FIG]

[1] [[Netscape Proxy]] が[[仕様書]]から削除された後も [CODE(HTTP)@en[[[Forwarded:]]]]
を実装していたようです。

** [CODE(HTTP)@en[X-Forwarded-*:]] ヘッダー群

[9] [CODE(HTTP)@en[[[Forwarded:]]]] が仕様から削除された後 [[Squid]] は
[CODE(HTTP)@en[[[X-Forwarded-For:]]]] をかわりに使うようになりました。
他の[[串]]もこれを実装した他、色々な関連[[ヘッダー]]を追加していきました。

[42] [CODE(HTTP)@en[[[Forwarded-For:]]]] を標準化する提案もありましたが、
これが [CODE(HTTP)@en[[[Forwarded:]]]] になりました。

;; [CODE(HTTP)@en[[[X-Forwarded-*:]]]] を参照。

** [CODE(HTTP)@en[Forwarded:]] ヘッダー (10年代)

[REFS[
- [4] [CITE@en[draft-petersson-forwarded-for-02 - Forwarded HTTP Extension]]
( ([TIME[2011-11-20 06:43:06 +09:00]] 版))
<http://tools.ietf.org/html/draft-petersson-forwarded-for-02>
- [5] [CITE@en[RFC 7239 - Forwarded HTTP Extension]] ([TIME[2014-09-07 05:21:07 +09:00]] 版) <https://tools.ietf.org/html/rfc7239>
]REFS]

[33] [CODE(HTTP)@en[[[Via:]]]] は既に広く用いられているため、これを拡張するわけにはいかなかった
[SRC[>>32]] とされています。

* 関連

[34] [CODE(HTTP)@en[[[Via:]]]] は用途が似ており歴史的関連性もありますが、
[CODE(HTTP)@en[[[Via:]]]] のみ追加されることや [CODE(HTTP)@en[[[Forwarded:]]]] のみ設定されることがあるので、
両者を対応付けることはできません [SRC[>>32]]。

[35] [[串]]は、[[要求]]に [CODE(HTTP)@en[[[X-Forwarded-*:]]]] が含まれている場合、
可能なら [CODE(HTTP)@en[[[Forwarded:]]]] に変換することが[RUBYB[推奨]@en[encourage]]されています
[SRC[>>36]]。

[37] しかし、例えば [CODE(HTTP)@en[[[X-Forwarded-For:]]]] と
[CODE(HTTP)@en[[[X-Forwarded-By:]]]] がどのような順序で追加されたかはわかりませんし、
[CODE(HTTP)@en[[[X-Forwarded-For:]]]] を削除すると[[転送]]先で互換性の問題が生じるかもしれません
[SRC[>>36]]。[[要求]]がどのような経路でその[[串]]まで到達したかわかっている場合を除き、
厳密には [CODE(HTTP)@en[[[X-Forwarded-*:]]]] をどう変換するべきか決定できません。
[CODE(HTTP)@en[[[X-Forwarded-*:]]]] の主たる用途である[[逆串]]では[[要求]]の到達経路を何ら過程できませんから、
実用上この変換はできないと思われます。

[38] また [CODE(HTTP)@en[[[X-Forwarded-*:]]]] を削除して [CODE(HTTP)@en[[[Forwarded:]]]]
を追加する実装や削除しないで追加する実装、あるいは [CODE(HTTP)@en[[[Forwarded:]]]]
を追加しない旧来の実装が混在する (あるいはいずれであるか事前に決定できない) 場合、
受信者の処理は [CODE(HTTP)@en[[[Forwarded:]]]] が追加されたせいで極めて複雑になります。

[39] 参考画像: [CITE[xkcd: Standards]] ([TIME[2014-10-24 15:09:27 +09:00]] 版) <http://xkcd.com/927/>

* 例

[25] 次のような例が示されています [SRC[>>8]]。

[PRE(HTTP code)[
Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17
]PRE]

* メモ

[31] [[RFC 7239]] の規定は情報の漏洩を防ぐために過剰に配慮しすぎているように見えます。
但し書きを適用しない限り、ほとんど実用に耐えない気がしますが・・・。
(例えば[[逆串]]が付与する [CODE(HTTP)@en[[[for]]]] が [[IPアドレス]]ではなく[[難読化識別子]]になっていたら、
裏側の[[アプリケーション鯖]]にとっては無用の長物でしかありません。)
そもそもが必須の機能ではないのに、何重にも保護する必要はどこにあるのでしょうかね。

[43] [CITE[''''''[''''''SPR-11856'''''']'''''' ServletUriComponentsBuilder should consider RFC-7239 Forwarded header - Spring JIRA]]
( ([TIME[2014-10-26 06:19:37 +09:00]] 版))
<https://jira.spring.io/browse/SPR-11856>

[44] [CITE@en[RFC 7239 - Implement Forward Header · Issue #36 · dstufft/fenrir]]
( ([TIME[2014-10-26 06:20:29 +09:00]] 版))
<https://github.com/dstufft/fenrir/issues/36>

[45] [CITE@en[RFC 8165 - Design Considerations for Metadata Insertion]]
([TIME[2017-05-11 14:53:35 +09:00]])
<https://tools.ietf.org/html/rfc8165#section-5>