HTTPリクエストヘッダを極める:構造からセキュリティ、CORS、実務運用まで完全解説

リクエストヘッダとは何か — 基本の理解

リクエストヘッダ(HTTPリクエストヘッダ)は、クライアント(ブラウザやAPIクライアント)がサーバにHTTPリクエストを送る際に付随するメタ情報です。リクエスト行(例:"GET /index.html HTTP/1.1")に続いて1行ずつ「ヘッダ名: 値」の形で送信され、サーバ側はこれを使って要求の内容を解釈・認証・ルーティング・キャッシュ制御などを行います。ヘッダはHTTPのやり取りで極めて重要な役割を果たしますが、その仕様や挙動はHTTPのバージョンや中継プロキシ、ブラウザのセキュリティポリシーなどに左右されます。

リクエストヘッダの構造と特性

  • 形式: "ヘッダ名: 値" のペアで表現される。複数行の同名ヘッダは結合されることがある(例:Cookieなど)。
  • 大文字小文字: HTTP/1.x ではヘッダ名は大文字小文字の区別がない(case-insensitive)。しかし HTTP/2/3 ではヘッダ名は小文字で表現されるのが規定です。
  • 必須と任意: 例えば HTTP/1.1 では Host ヘッダが必須です。その他は用途に応じて任意に付けられます。
  • カスタムヘッダ: 開発者は "X-*" プレフィックスを使ったり(歴史的慣習)、任意のカスタムヘッダを定義して独自のメタ情報を運ぶことができます。ただし最近は標準ヘッダ名を使うかプロジェクト固有のプレフィックスを使うのが一般的です。

代表的なリクエストヘッダと用途

  • Host: 接続先のホスト名(+ポート)。HTTP/1.1で必須。仮想ホスティングの判定に使う。
  • User-Agent: クライアントソフトの識別子(ブラウザ名やバージョン)。解析・表示調整・統計に利用されるが、偽装されやすい。
  • Accept, Accept-Language, Accept-Encoding: クライアントが許容するメディアタイプや言語、圧縮方式を示す。サーバはこれを元に最適なレスポンスを返す。
  • Authorization: Basic/Bearer等の認証トークンを送る。
  • Cookie: クッキーを送信する(セッション識別など)。ブラウザはセキュリティポリシーに基づき送信を制御する。
  • Content-Type, Content-Length: POST/PUTなどボディを伴うリクエストでボディの型とサイズを示す。
  • Referer(歴史的に "referrer" の綴りミス): リクエストが来た元のURLを示す。プライバシー上の考慮があるため制御される。
  • Cache-Control, If-Modified-Since, If-None-Match: キャッシュの挙動や条件付きリクエストに使う。
  • X-Forwarded-For, Forwarded: プロキシ/ロードバランサ経由でのクライアントIP情報を示す(信頼できる中継でのみ採用)。
  • Connection, Upgrade: 接続の管理やプロトコル切替に関する制御(HTTP/2では扱いが変わる)。

HTTPバージョンによる違い(HTTP/1.1、HTTP/2、HTTP/3)

HTTP/1.1 はテキストベースでヘッダは行単位で送られます。HTTP/2 ではヘッダはバイナリ化・圧縮(HPACK)され、ストリームごとに「pseudo-headers(:method, :path, :authority, :scheme)」が導入されます。HTTP/3(QUICベース)でも同様の概念(QPACKや類似の圧縮方式)が使われます。これにより同時接続性や効率は向上しますが、ヘッダ圧縮に起因するサイドチャネル攻撃(CRIME/BREACHなど)や実装上の注意点も生じます。

ブラウザ側の制約と「禁止ヘッダ」

ブラウザのJavaScript(fetch、XMLHttpRequest)から任意のヘッダを勝手に送れるわけではありません。セキュリティ上、ブラウザは一部のヘッダを設定不可としています(例:Host、Content-Length、Connection、Cookie 等の一部、または自動的に付加されるもの)。これらは「forbidden header names」として仕様で制限されており、意図しないリクエスト改変やセキュリティ破壊を防ぎます。

CORS(クロスオリジン)とプリフライト

ブラウザが異なるオリジンにリクエストする際、特にカスタムヘッダや特定のメソッドを使う場合は事前にプリフライト(OPTIONS)を送ることがあります。プリフライトでは Access-Control-Request-Method や Access-Control-Request-Headers が使われ、サーバは Access-Control-Allow-Origin や Access-Control-Allow-Headers で許可を返します。サーバ側で適切にヘッダを返さないとブラウザはリクエストをブロックします(CORSによりクライアント保護)。

セキュリティ上の懸念と対策

  • ヘッダインジェクション(CRLF注入): ヘッダに改行を注入してレスポンス分割などを招く攻撃。ヘッダ値は厳密に検証・サニタイズし、改行を許さないようにする。
  • Hostヘッダ攻撃: Host を信頼して生成したURLでオープンリダイレクトやキャッシュ汚染が起きるため、業務的に信頼できるホストのみ受け入れるか、ホスト検証を行う。
  • 秘密情報の露呈: Authorization や Cookie 等の機密情報は HTTPS を必ず使って送信し、同時に SameSite/CSP/HSTS 等の追加対策を利用する。
  • プロキシ経由の信用: X-Forwarded-For 等のヘッダは偽装可能。信頼できるリバースプロキシやロードバランサからの情報のみ受け入れる設計が必要。

実務で注意するポイント

  • サイズ制限: RFCで明確な上限は無いが、多くのサーバーはヘッダ数・ヘッダ長の上限を設定している(例:ApacheのLimitRequestFieldSize=8190、Nginxのlarge_client_header_buffers など)。大きなCookieや多量のカスタムヘッダはリクエスト拒否の原因になり得る。
  • キャッシュ制御: Vary ヘッダはレスポンスのキャッシュの差異を指定する。Accept-Language や Cookie を理由に Vary を適切に使わないとキャッシュ汚染が起きる。
  • ログとプライバシー: ヘッダはサーバログに残ることがあるため、個人情報や認証情報を不用意にログ出力しない。
  • バージョン固有の挙動: HTTP/2ではヘッダは低レベルで圧縮・暗号化されるが、同時に実装依存の注意点(例:ヘッダの順序は意味を持たない、名前は小文字)がある。

実例: よく見るリクエストヘッダの一覧

  • GET /path HTTP/1.1
  • Host: example.com
  • User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
  • Accept: text/html,application/xhtml+xml,...
  • Accept-Language: ja,en-US;q=0.9
  • Accept-Encoding: gzip, deflate, br
  • Connection: keep-alive
  • Cookie: sessionid=...; csrftoken=...
  • Authorization: Bearer

ヘッダの確認・操作方法(現場でよく使うツール)

  • ブラウザ開発者ツール(Network タブ): リクエスト・レスポンスヘッダを可視化
  • curl: -I(ヘッダのみ取得)、-v(詳細表示)、-H "Name: Value"(ヘッダ追加)
  • tcpdump / Wireshark: ロー・レベルでパケットを解析(暗号化されていない通信で有効)
  • サーバログ: アクセスログに記録されたヘッダやリモート情報を確認

プログラムからのヘッダ操作(例)

fetch や curl、サーバサイドのHTTPライブラリを使ってヘッダを追加・変更するのは一般的です。ただし前述の通りブラウザでは禁止ヘッダや自動付与されるヘッダを操作できない場合があります。API設計では認証情報を Authorization ヘッダや標準の手段で扱うのが望ましいです。

まとめ

リクエストヘッダはクライアントからサーバへ送る「文脈情報」であり、認証、言語選択、圧縮、キャッシュ、プロキシ経由の情報など多くの用途を持ちます。HTTPのバージョン、ブラウザのセキュリティ制約、中継プロキシ、サーバ設定(ヘッダサイズ制限など)を理解した上で設計・実装・運用を行うことが重要です。特にセキュリティやプライバシーに関する落とし穴(ヘッダインジェクション、機密情報の漏洩、偽装可能なプロキシヘッダ等)は実務で常に注意する必要があります。

参考文献