[インデックス 17018] ファイルの概要
このコミットは、Go言語の標準ライブラリである net/http
パッケージ内の Response.Header
フィールドに関するドキュメントの修正です。具体的には、HTTPレスポンスヘッダーにおいて、同じキーを持つ複数のヘッダーがどのように扱われるかについての記述をより正確にするための変更が行われました。
コミット
commit 910caf93454d177fee459a6e65cb4f5d8e0b56ad
Author: Josh Bleecher Snyder <josharian@gmail.com>
Date: Sun Aug 4 11:23:17 2013 -0700
net/http: fix Response.Header documentation for multiple headers with same key
Whether the keys are concatenated or separate (or a mixture) depends on the server.
Fixes #5979.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12433043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/910caf93454d177fee459a6e65cb4f5d8e0b56ad
元コミット内容
net/http: fix Response.Header documentation for multiple headers with same key
このコミットの目的は、net/http
パッケージの Response.Header
のドキュメントを修正し、同じキーを持つ複数のヘッダーの扱いに関する記述をより正確にすることです。元のドキュメントでは、同じキーを持つ複数のヘッダーは常にカンマ区切りで連結されると記述されていましたが、実際にはサーバーの実装によって連結される場合とされない場合があるため、その点を明確にする変更です。
変更の背景
Go言語の net/http
パッケージは、HTTPクライアントおよびサーバーの実装を提供します。Response
構造体には、受信したHTTPレスポンスのヘッダー情報を含む Header
フィールドがあります。この Header
フィールドは map[string][]string
型であり、ヘッダー名(キー)からその値のリストへのマッピングを提供します。
HTTP/1.1の仕様であるRFC 2616のセクション4.2では、同じヘッダーフィールド名がメッセージ内で複数回出現する場合の扱いについて規定しています。このセクションでは、一部のヘッダーフィールド(例: Content-Type
)は単一の値しか持てないが、他のヘッダーフィールド(例: Set-Cookie
)は複数回出現することが許容されると述べています。また、同じヘッダーフィールド名が複数回出現する場合、それらはカンマで区切られた単一のフィールド値として扱われるべきであるとされています。
しかし、実際のサーバーの実装においては、このRFCの推奨に従わず、同じキーを持つ複数のヘッダーを個別のヘッダーとして送信する場合や、一部を連結し、一部を個別に送信するような混合した形式で送信する場合があります。Goの net/http
パッケージは、このような多様なサーバーの挙動に対応する必要があります。
元の Response.Header
のドキュメントでは、「If the response had multiple headers with the same key, they will be concatenated, with comma delimiters.」と記述されており、これは常に連結されるという誤解を招く可能性がありました。このコミットは、この記述が現実のHTTPサーバーの挙動と完全に一致しないことを認識し、より正確な表現に修正することを目的としています。具体的には、「they will be concatenated」を「they may be concatenated」に変更することで、サーバーの実装に依存するというニュアンスを加えています。
前提知識の解説
HTTPヘッダー
HTTPヘッダーは、HTTPリクエストまたはレスポンスのメタデータを提供するキーと値のペアです。これらは、クライアントとサーバーが通信する際に、コンテンツのタイプ、エンコーディング、キャッシュ制御、認証情報など、様々な情報を交換するために使用されます。
例:
Content-Type: application/json
Content-Length: 1234
Cache-Control: no-cache, no-store
Set-Cookie: sessionid=abc; Path=/
Set-Cookie: preferences=darkmode; Path=/
RFC 2616 (HTTP/1.1)
RFC 2616は、HTTP/1.1プロトコルの主要な仕様を定義した文書です。このRFCは、HTTPメッセージの構造、メソッド、ヘッダーフィールド、ステータスコードなど、HTTPのあらゆる側面を詳細に記述しています。
特に、セクション4.2「Message Headers」では、ヘッダーフィールドの構文と意味論について説明されています。このセクションには、同じヘッダーフィールド名が複数回出現する場合の扱いに関する規定が含まれています。RFC 2616は、複数のヘッダーフィールドが同じフィールド名を持つ場合、それらはカンマで区切られた単一のフィールド値として扱われるべきであると推奨しています。これは、HTTPヘッダーの解析において、同じキーを持つ複数の値をどのように解釈すべきかという指針を提供します。
Go言語の net/http
パッケージ
net/http
パッケージは、Go言語でHTTPクライアントとサーバーを構築するための基本的な機能を提供します。このパッケージは、HTTPプロトコルの詳細を抽象化し、開発者が簡単にWebアプリケーションを構築できるようにします。
http.Response
構造体: HTTPレスポンスを表す構造体です。サーバーからの応答のステータスコード、プロトコルバージョン、ヘッダー、ボディなどの情報を含みます。http.Header
型:map[string][]string
のエイリアスであり、HTTPヘッダーを表すために使用されます。キーはヘッダー名(例: "Content-Type")、値はそのヘッダー名に関連付けられた文字列のリストです。これにより、同じヘッダー名が複数回出現する場合でも、すべての値を保持できます。
HTTPヘッダーの連結と非連結
HTTPヘッダーの処理において、同じキーを持つ複数のヘッダー値は、RFCの推奨に従ってカンマで連結されることがあります。例えば、Cache-Control: no-cache
と Cache-Control: no-store
が別々に送信された場合、クライアント側で Cache-Control: no-cache, no-store
のように単一のヘッダーとして解釈されることがあります。
しかし、すべてのヘッダーがこのように連結されるわけではありません。特に Set-Cookie
ヘッダーのように、個々の値が独立した意味を持つ場合は、連結されずに複数回出現することが一般的です。サーバーの実装によっては、RFCの推奨に従わず、連結可能なヘッダーであっても個別に送信する場合があります。
このコミットは、Goの net/http
パッケージが、このようなサーバー側の多様な挙動を考慮し、ドキュメントをより正確に記述することの重要性を示しています。
技術的詳細
このコミットの技術的な変更は非常に小さいですが、その背後にある意味は重要です。変更は src/pkg/net/http/response.go
ファイルの Response
構造体の Header
フィールドのコメントにあります。
元のコメント:
// Header maps header keys to values. If the response had multiple
// headers with the same key, they will be concatenated, with comma
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers
// be semantically equivalent to a comma-delimited sequence.) Values
// duplicated by other fields in this struct (e.g., ContentLength) are
変更後のコメント:
// Header maps header keys to values. If the response had multiple
// headers with the same key, they may be concatenated, with comma
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers
// be semantically equivalent to a comma-delimited sequence.) Values
// duplicated by other fields in this struct (e.g., ContentLength) are
変更点は they will be concatenated
が they may be concatenated
になった点です。
この変更は、Goの net/http
パッケージがHTTPレスポンスヘッダーをどのように処理するかという内部的なロジックを変更するものではありません。むしろ、そのロジックが外部からどのように見えるか、つまりドキュメントがその挙動をどのように説明するかを修正しています。
Response.Header
は map[string][]string
型であるため、Goの内部では同じキーを持つ複数のヘッダー値は常に文字列のスライスとして保持されます。例えば、サーバーが X-Custom-Header: value1
と X-Custom-Header: value2
を送信した場合、Goの Response.Header["X-Custom-Header"]
は []string{"value1", "value2"}
となります。
問題は、この []string
がどのように生成されるか、そしてその生成過程でサーバーが送信した複数のヘッダーが連結される可能性があるという点です。RFC 2616は、一部のヘッダーについてはカンマ区切りで連結された単一のヘッダーとして扱われるべきだと推奨していますが、すべてのサーバーがこの推奨に厳密に従うわけではありません。また、Set-Cookie
のように、連結されるべきではないヘッダーも存在します。
このドキュメントの修正は、Goの net/http
パッケージが受信したヘッダーを処理する際に、サーバーが複数のヘッダーを送信した場合に、それらが必ずしもGoの内部でカンマ区切りで連結された単一の文字列として表現されるわけではない、という事実を反映しています。Goは、サーバーから受信した生のヘッダーを可能な限り忠実に []string
として保持しようとしますが、その過程で一部のヘッダーがRFCの推奨に従って連結される可能性も示唆しています。
「Whether the keys are concatenated or separate (or a mixture) depends on the server.」というコミットメッセージの追加説明は、この点をさらに強調しています。つまり、Goのクライアント側でのヘッダーの解釈は、サーバーがどのようにヘッダーを送信したかに依存するということを明確にしています。これは、Goの net/http
パッケージが堅牢であり、多様なサーバーの実装に対応できることを示唆しています。
コアとなるコードの変更箇所
変更は src/pkg/net/http/response.go
ファイルの33行目です。
--- a/src/pkg/net/http/response.go
+++ b/src/pkg/net/http/response.go
@@ -32,7 +32,7 @@ type Response struct {
ProtoMinor int // e.g. 0
// Header maps header keys to values. If the response had multiple
- // headers with the same key, they will be concatenated, with comma
+ // headers with the same key, they may be concatenated, with comma
// delimiters. (Section 4.2 of RFC 2616 requires that multiple headers
// be semantically equivalent to a comma-delimited sequence.) Values
// duplicated by other fields in this struct (e.g., ContentLength) are
コアとなるコードの解説
変更された行は、Response
構造体の Header
フィールドのドキュメンテーションコメントの一部です。
元のコメント:
// headers with the same key, they will be concatenated, with comma
修正後のコメント:
// headers with the same key, they may be concatenated, with comma
この変更は、will be
(〜されるだろう、確実に〜される) を may be
(〜されるかもしれない、可能性として〜される) に置き換えることで、同じキーを持つ複数のHTTPヘッダーがGoの Response.Header
に格納される際に、必ずしもカンマ区切りで連結されるわけではないという事実を反映しています。
これは、HTTPプロトコルの柔軟性と、サーバーの実装がRFCの推奨に常に厳密に従うとは限らないという現実を考慮したものです。Goの net/http
パッケージは、可能な限り正確に受信したヘッダーを表現しようとしますが、その最終的な形式(連結されるか、個別の値として保持されるか)は、サーバーの挙動に依存するというニュアンスをドキュメントに加えています。
この修正は、Goの net/http
パッケージのユーザーが、Response.Header
を扱う際に、同じキーを持つ複数のヘッダー値が常に連結された単一の文字列として扱われると誤解するのを防ぐことを目的としています。これにより、開発者はより堅牢なコードを記述し、多様なHTTPサーバーからのレスポンスを適切に処理できるようになります。
関連リンク
- Go issue #5979: https://github.com/golang/go/issues/5979
- Go CL 12433043: https://golang.org/cl/12433043
参考にした情報源リンク
- RFC 2616, Section 4.2 Message Headers: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
- Go
net/http
package documentation: https://pkg.go.dev/net/http - Go
http.Header
type: https://pkg.go.dev/net/http#Header - Go
http.Response
struct: https://pkg.go.dev/net/http#Response