この記事はRFC7230をもとにしています。つまみ食い読みをしているので、間違っていたらすみません。編集リクエストをいただけると幸いです。
HTTP では、クライアントサーバーモデルに基づき、クライアントがサーバーへリソースを要求(リクエスト)し、サーバーはそれに応答(レスポンス)を返します。
クライアントやサーバーが発するものはメッセージと呼ばれます。メッセージは
- 0個以上のヘッダフィールド、
- ヘッダフィールドの終わりを示す空の行、
- オプション(あってもなくてもよい)としてメッセージボディ
からなります。
この記事では HTTP リクエストの特に Host ヘッダフィールドについて理解することを目的とします。
HTTP リクエストメッセージとレスポンスメッセージは、以下のようなものです。(RFC7230 §2.1から引用)
Client request:
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com // ←ここが Hostヘッダフィールド
Accept-Language: en, mi
Server response:
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
Hello World! My payload includes a trailing CRLF.
HTTP リクエストの Host ヘッダフィールドは、アクセスしたい URI とポートの情報をもちます。
Host: www.example.com
もしくは
Host: www.example.com:80
サーバーは単一の IP アドレスについて複数のホストネームを持つことができます。どのホストネームでリソースを要求されたかによって、提供するリソースを振り分ける必要があります。HTTP リクエストを受け取ったサーバーは Host ヘッダを見ることによって、提供すべきリソースを決めることができます。
HTTP リクエストメッセージは必ず Host ヘッダフィールドを含む必要があります (MUST)。
上の例のリクエストメッセージの1行目
GET /hello.txt HTTP/1.1
のことをリクエストラインと呼びます。リクエストラインの GET
の直後、この例では /hello.txt
の部分をリクエストターゲット と言います。リクエストターゲットはターゲットの URI から作られ、その書き方は4種類あります。
Authority コンポーネント (johndoe@www.example.com
みたいなもの、ユーザー名と @
はなくてもいいので通常は www.example.com
の部分) がターゲット URI に含まれる場合は、 Host ヘッダフィールドにも同じ値 (www.example.com
) をもつ必要があります (MUST)。
逆にターゲット URI に authority コンポーネントが欠けている場合は、 Host ヘッダフィールドの値は空でなければなりません (MUST)。1
Host ヘッダフィールドの値はリクエストを扱うのに重要な情報ですから、ユーザーエージェント(ブラウザとか)はリクエストラインのすぐ直後に Host ヘッダを生成すべきです (SHOULD)。例えば http://www.example.org/pub/WWW/
へのリクエストは
GET /pub/WWW/ HTTP/1.1
Host: www.example.org
というようになります。
HTTP/1.1 リクエストでは、クライアントはリクエストターゲットを absolute-form (リクエストターゲット参照) で書いた場合であっても Host ヘッダを送らなければなりません (MUST)。Host を実装していない可能性がある古代の HTTP/1.0 プロキシはを経由しても Host 情報が渡されるようにするためです。
プロキシが absolute-form のリクエストターゲットを受け取ったとき、プロキシは Host ヘッダフィールドを無視しリクエストターゲットのホスト情報で置き換えなければなりません (MUST)。そのようなリクエストを転送するプロキシも同様です。
Host ヘッダフィールドはアプリケーションレベルでのルーティング機構として振る舞うため、共有キャッシュポイズニングや意図しないサーバーへのリダイレクトを狙うマルウェアの標的となりがちです。透過プロキシがリクエストを内部サーバーに Host フィールドの値に基づいて振り分けていたり、共有キャッシュのキャッシュキーとして用いられていたりしていて、プロキシを通る通信がそのホストにとって有効な IP をターゲットとしているかの検証をしていない場合には、特に脆弱です。
Host ヘッダフィールドがない、または複数ある、または無効な値になっている HTTP/1.1 リクエストに対してサーバーは 400 Bad Request を返さなければなりません (MUST)。
-
Host ヘッダフィールドが空、すなわち authority コンポーネントがない状況というのはおそらく何らかの異常が起きた状況だと思うのですが、具体的にはどのような状況なのでしょうか。ご存知の方がいらっしゃいましたらコメント欄等で教えていただけると幸いです。 ↩