[インデックス 19387] ファイルの概要
このコミットは、Go言語の net/http
パッケージにおいて、HTTP 204 (No Content) レスポンスに Content-Type
ヘッダーを含めることを許可する変更です。以前の Content-Length
に関する修正(Issue 6685に関連)によって意図せず Content-Type
ヘッダーが抑制されるようになっていた問題を修正します。
コミット
net/http: allow Content-Type on 204 responses
Accidental change from fixing Content-Length on 204s
in http://golang.org/issue/6685 earlier.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/92400047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4c8de36e2bb01af620cc2b32d2dba806e9f07f9b
元コミット内容
commit 4c8de36e2bb01af620cc2b32d2dba806e9f07f9b
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Fri May 16 15:39:59 2014 -0700
net/http: allow Content-Type on 204 responses
Accidental change from fixing Content-Length on 204s
in http://golang.org/issue/6685 earlier.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/92400047
変更の背景
この変更は、Goの net/http
パッケージにおける以前の修正に起因する意図しない副作用を是正するために行われました。具体的には、HTTP 204 (No Content) レスポンスにおける Content-Length
ヘッダーの取り扱いを修正する過程で(これは http://golang.org/issue/6685
に関連する作業でした)、誤って Content-Type
ヘッダーも抑制されるようになってしまいました。
HTTP 204 レスポンスは、リクエストが正常に処理されたものの、レスポンスボディにコンテンツが含まれないことを示します。このようなレスポンスでは Content-Length
や Transfer-Encoding
といったボディに関連するヘッダーは通常抑制されますが、Content-Type
ヘッダーは必ずしも抑制されるべきではありません。例えば、クライアントが特定の Content-Type
を期待している場合や、APIの設計上、メタデータとして Content-Type
を含めることが有用な場合があります。
RFC 2616などのHTTP仕様では、HTTP 304 (Not Modified) レスポンスに対しては、Content-Type
を含む「エンティティヘッダー」を厳しく抑制するよう規定されていますが、204 レスポンスに対してはそこまで厳格な規定はありません。このコミットは、この仕様のニュアンスを正しく反映し、204 レスポンスにおける Content-Type
ヘッダーの不必要な抑制を解除することを目的としています。
前提知識の解説
HTTP ステータスコード 204 (No Content)
HTTP 204 "No Content" は、サーバーがリクエストを正常に処理したが、レスポンスボディとしてコンテンツを返さないことを示すステータスコードです。例えば、リソースの更新リクエストが成功したが、クライアントに新しいデータを返す必要がない場合などに使用されます。204 レスポンスにはメッセージボディが含まれないため、Content-Length
や Transfer-Encoding
といったボディの長さを指定するヘッダーは通常含まれません。
HTTP ステータスコード 304 (Not Modified)
HTTP 304 "Not Modified" は、クライアントが条件付きGETリクエスト(例: If-Modified-Since
や If-None-Match
ヘッダーを使用)を送信し、リクエストされたリソースが変更されていない場合に返されるステータスコードです。この場合もレスポンスボディは含まれません。RFC 2616のセクション 10.3.5 では、304 レスポンスは Content-Type
を含む「エンティティヘッダー」を送信してはならないと明確に規定されています。これは、クライアントがキャッシュされたリソースのヘッダーを使用することを意図しているためです。
HTTP ヘッダーの抑制
HTTPレスポンスにおいて、特定のステータスコード(特にボディを持たないもの)の場合、一部のヘッダーは送信されるべきではありません。
Content-Length
: レスポンスボディの長さをバイト単位で示すヘッダー。ボディがない場合は不要。Transfer-Encoding
: メッセージボディに適用されたエンコーディング形式(例:chunked
)を示すヘッダー。ボディがない場合は不要。Content-Type
: レスポンスボディのメディアタイプ(例:application/json
,text/html
)を示すヘッダー。ボディがない場合は、その必要性が状況によって異なります。304 の場合はRFCで抑制が義務付けられていますが、204 の場合はそうではありません。
Go言語の net/http
パッケージ
net/http
はGo言語の標準ライブラリで、HTTPクライアントとサーバーの実装を提供します。このパッケージは、HTTPリクエストの解析、レスポンスの生成、ヘッダーの管理など、HTTP通信の低レベルな詳細を抽象化します。サーバーサイドでは、ResponseWriter
インターフェースを通じてレスポンスヘッダーの設定やボディの書き込みを行います。
技術的詳細
このコミットの技術的な核心は、Goの net/http
パッケージがレスポンスヘッダーを処理するロジック、特にボディを持たないHTTPステータスコード(204や304など)に対するヘッダーの抑制方法の変更にあります。
以前の実装では、server.go
内の writeHeader
関数において、bodyAllowedForStatus(code)
が false
を返す(つまり、そのステータスコードではボディが許可されない)場合、一律に Content-Type
、Content-Length
、Transfer-Encoding
の各ヘッダーを削除していました。これは、HTTP 304 レスポンスの要件(RFC 2616 Section 10.3.5)を満たすためのものでしたが、HTTP 204 レスポンスに対しても同様に Content-Type
を削除してしまうという副作用がありました。
このコミットでは、この一律の抑制ロジックを改善し、ステータスコードに応じて抑制するヘッダーをより細かく制御するように変更しました。
-
suppressedHeaders
関数の導入:src/pkg/net/http/transfer.go
にsuppressedHeaders(status int) []string
という新しい関数が導入されました。この関数は、与えられたHTTPステータスコードに基づいて、抑制すべきヘッダー名のスライスを返します。status == 304
の場合:suppressedHeaders304
(定義は{"Content-Type", "Content-Length", "Transfer-Encoding"}
) を返します。これはRFC 2616の規定に厳密に従います。!bodyAllowedForStatus(status)
(かつ304ではない) の場合:suppressedHeadersNoBody
(定義は{"Content-Length", "Transfer-Encoding"}
) を返します。これにより、204のようなボディを持たないがContent-Type
の抑制が不要なステータスコードに対して、Content-Type
ヘッダーが保持されるようになります。- それ以外の場合:
nil
を返し、ヘッダーの抑制は行いません。
-
server.go
のwriteHeader
の変更:src/pkg/net/http/server.go
内のwriteHeader
関数が修正され、以前の一律削除ロジックがsuppressedHeaders
関数を呼び出す形に置き換えられました。// 変更前: // if !bodyAllowedForStatus(code) { // for _, k := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} { // delHeader(k) // } // } else { ... } // 変更後: // if bodyAllowedForStatus(code) { // // ... (Content-Type sniffing logic) // } else { // for _, k := range suppressedHeaders(code) { // delHeader(k) // } // }
この変更により、
bodyAllowedForStatus(code)
がfalse
の場合でも、Content-Type
がsuppressedHeaders
によって抑制されない限り、レスポンスヘッダーに残るようになります。 -
テストケースの追加:
src/pkg/net/http/serve_test.go
にTestContentTypeOkayOn204
という新しいテストケースが追加されました。このテストは、HTTP 204 レスポンスに対してContent-Type
ヘッダーが正しく含まれ、Content-Length
ヘッダーが抑制されることを検証します。これにより、意図した動作が保証されます。
この変更は、HTTP仕様の解釈をより正確に反映し、Goの net/http
パッケージの堅牢性と柔軟性を向上させるものです。
コアとなるコードの変更箇所
src/pkg/net/http/serve_test.go
:TestContentTypeOkayOn204
という新しいテスト関数が追加されました。このテストは、204 レスポンスでContent-Type
ヘッダーが設定され、Content-Length
ヘッダーが抑制されることを確認します。
src/pkg/net/http/server.go
:writeHeader
関数内のヘッダー抑制ロジックが変更されました。以前はbodyAllowedForStatus
に基づいて一律にContent-Type
などが削除されていましたが、新しいsuppressedHeaders
関数を使用して、ステータスコードに応じた適切なヘッダーのみを削除するように修正されました。
src/pkg/net/http/transfer.go
:suppressedHeaders304
とsuppressedHeadersNoBody
という2つの文字列スライス変数が追加されました。これらはそれぞれ、304 レスポンスとボディを持たない他のレスポンス(204など)で抑制されるべきヘッダーのリストを定義します。suppressedHeaders(status int) []string
という新しい関数が追加されました。この関数は、与えられたステータスコードに基づいて、どのヘッダーを抑制すべきかを決定し、対応するヘッダー名のスライスを返します。
コアとなるコードの解説
-
src/pkg/net/http/serve_test.go
の変更:TestContentTypeOkayOn204
テストは、このコミットが修正しようとしている問題を直接検証します。ハンドラ内でContent-Length
とContent-Type
を設定し、204 ステータスコードを返します。その後、レスポンスを解析し、Content-Type
が存在し、Content-Length
が存在しないことをアサートします。これにより、変更が正しく機能していることが保証されます。 -
src/pkg/net/http/server.go
の変更:writeHeader
関数は、HTTPレスポンスのヘッダーを実際に書き込むGoのHTTPサーバーの中核部分です。この変更により、ヘッダーの抑制ロジックがより洗練され、HTTP仕様のニュアンス(特に304と204の違い)を正確に反映するようになりました。以前はContent-Type
が不必要に削除されていましたが、この修正により、204 レスポンスではContent-Type
が保持されるようになります。 -
src/pkg/net/http/transfer.go
の変更:suppressedHeaders
関数は、ヘッダー抑制のポリシーをカプセル化します。これにより、server.go
のwriteHeader
関数は、どのヘッダーを削除すべきかという詳細なロジックから解放され、よりクリーンなコードになります。suppressedHeaders304
とsuppressedHeadersNoBody
の導入は、異なるステータスコードに対する異なるヘッダー抑制ルールを明確に定義し、コードの可読性と保守性を向上させます。
これらの変更は全体として、Goの net/http
パッケージがHTTP仕様に準拠しつつ、より柔軟なヘッダー処理を可能にすることを目指しています。
関連リンク
- Go Change List (CL) for this commit: https://golang.org/cl/92400047
- 関連する以前のIssue (Issue 6685): このコミットメッセージで参照されていますが、直接的なGoのIssueトラッカー上のリンクは見つかりませんでした。しかし、
Content-Length
の修正に関連するものであったことが示唆されています。
参考にした情報源リンク
- RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1, Section 10.3.5 304 Not Modified: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
- HTTP 204 No Content Status Code: 一般的なHTTP仕様に関する情報源 (例: MDN Web Docsなど)
- Go言語の
net/http
パッケージのドキュメント (Go公式ドキュメント) - Web検索結果: "HTTP 204 response Content-Type", "golang issue 6685"```markdown
[インデックス 19387] ファイルの概要
このコミットは、Go言語の net/http
パッケージにおいて、HTTP 204 (No Content) レスポンスに Content-Type
ヘッダーを含めることを許可する変更です。以前の Content-Length
に関する修正(Issue 6685に関連)によって意図せず Content-Type
ヘッダーが抑制されるようになっていた問題を修正します。
コミット
net/http: allow Content-Type on 204 responses
Accidental change from fixing Content-Length on 204s
in http://golang.org/issue/6685 earlier.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/92400047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4c8de36e2bb01af620cc2b32d2dba806e9f07f9b
元コミット内容
commit 4c8de36e2bb01af620cc2b32d2dba806e9f07f9b
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Fri May 16 15:39:59 2014 -0700
net/http: allow Content-Type on 204 responses
Accidental change from fixing Content-Length on 204s
in http://golang.org/issue/6685 earlier.
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/92400047
変更の背景
この変更は、Goの net/http
パッケージにおける以前の修正に起因する意図しない副作用を是正するために行われました。具体的には、HTTP 204 (No Content) レスポンスにおける Content-Length
ヘッダーの取り扱いを修正する過程で(これは http://golang.org/issue/6685
に関連する作業でした)、誤って Content-Type
ヘッダーも抑制されるようになってしまいました。
HTTP 204 レスポンスは、リクエストが正常に処理されたものの、レスポンスボディにコンテンツが含まれないことを示します。このようなレスポンスでは Content-Length
や Transfer-Encoding
といったボディに関連するヘッダーは通常抑制されますが、Content-Type
ヘッダーは必ずしも抑制されるべきではありません。例えば、クライアントが特定の Content-Type
を期待している場合や、APIの設計上、メタデータとして Content-Type
を含めることが有用な場合があります。
RFC 2616などのHTTP仕様では、HTTP 304 (Not Modified) レスポンスに対しては、Content-Type
を含む「エンティティヘッダー」を厳しく抑制するよう規定されていますが、204 レスポンスに対してはそこまで厳格な規定はありません。このコミットは、この仕様のニュアンスを正しく反映し、204 レスポンスにおける Content-Type
ヘッダーの不必要な抑制を解除することを目的としています。
前提知識の解説
HTTP ステータスコード 204 (No Content)
HTTP 204 "No Content" は、サーバーがリクエストを正常に処理したが、レスポンスボディとしてコンテンツを返さないことを示すステータスコードです。例えば、リソースの更新リクエストが成功したが、クライアントに新しいデータを返す必要がない場合などに使用されます。204 レスポンスにはメッセージボディが含まれないため、Content-Length
や Transfer-Encoding
といったボディの長さを指定するヘッダーは通常含まれません。
HTTP ステータスコード 304 (Not Modified)
HTTP 304 "Not Modified" は、クライアントが条件付きGETリクエスト(例: If-Modified-Since
や If-None-Match
ヘッダーを使用)を送信し、リクエストされたリソースが変更されていない場合に返されるステータスコードです。この場合もレスポンスボディは含まれません。RFC 2616のセクション 10.3.5 では、304 レスポンスは Content-Type
を含む「エンティティヘッダー」を送信してはならないと明確に規定されています。これは、クライアントがキャッシュされたリソースのヘッダーを使用することを意図しているためです。
HTTP ヘッダーの抑制
HTTPレスポンスにおいて、特定のステータスコード(特にボディを持たないもの)の場合、一部のヘッダーは送信されるべきではありません。
Content-Length
: レスポンスボディの長さをバイト単位で示すヘッダー。ボディがない場合は不要。Transfer-Encoding
: メッセージボディに適用されたエンコーディング形式(例:chunked
)を示すヘッダー。ボディがない場合は不要。Content-Type
: レスポンスボディのメディアタイプ(例:application/json
,text/html
)を示すヘッダー。ボディがない場合は、その必要性が状況によって異なります。304 の場合はRFCで抑制が義務付けられていますが、204 の場合はそうではありません。
Go言語の net/http
パッケージ
net/http
はGo言語の標準ライブラリで、HTTPクライアントとサーバーの実装を提供します。このパッケージは、HTTPリクエストの解析、レスポンスの生成、ヘッダーの管理など、HTTP通信の低レベルな詳細を抽象化します。サーバーサイドでは、ResponseWriter
インターフェースを通じてレスポンスヘッダーの設定やボディの書き込みを行います。
技術的詳細
このコミットの技術的な核心は、Goの net/http
パッケージがレスポンスヘッダーを処理するロジック、特にボディを持たないHTTPステータスコード(204や304など)に対するヘッダーの抑制方法の変更にあります。
以前の実装では、server.go
内の writeHeader
関数において、bodyAllowedForStatus(code)
が false
を返す(つまり、そのステータスコードではボディが許可されない)場合、一律に Content-Type
、Content-Length
、Transfer-Encoding
の各ヘッダーを削除していました。これは、HTTP 304 レスポンスの要件(RFC 2616 Section 10.3.5)を満たすためのものでしたが、HTTP 204 レスポンスに対しても同様に Content-Type
を削除してしまうという副作用がありました。
このコミットでは、この一律の抑制ロジックを改善し、ステータスコードに応じて抑制するヘッダーをより細かく制御するように変更しました。
-
suppressedHeaders
関数の導入:src/pkg/net/http/transfer.go
にsuppressedHeaders(status int) []string
という新しい関数が導入されました。この関数は、与えられたHTTPステータスコードに基づいて、抑制すべきヘッダー名のスライスを返します。status == 304
の場合:suppressedHeaders304
(定義は{"Content-Type", "Content-Length", "Transfer-Encoding"}
) を返します。これはRFC 2616の規定に厳密に従います。!bodyAllowedForStatus(status)
(かつ304ではない) の場合:suppressedHeadersNoBody
(定義は{"Content-Length", "Transfer-Encoding"}
) を返します。これにより、204のようなボディを持たないがContent-Type
の抑制が不要なステータスコードに対して、Content-Type
ヘッダーが保持されるようになります。- それ以外の場合:
nil
を返し、ヘッダーの抑制は行いません。
-
server.go
のwriteHeader
の変更:src/pkg/net/http/server.go
内のwriteHeader
関数が修正され、以前の一律削除ロジックがsuppressedHeaders
関数を呼び出す形に置き換えられました。// 変更前: // if !bodyAllowedForStatus(code) { // for _, k := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} { // delHeader(k) // } // } else { ... } // 変更後: // if bodyAllowedForStatus(code) { // // ... (Content-Type sniffing logic) // } else { // for _, k := range suppressedHeaders(code) { // delHeader(k) // } // }
この変更により、
bodyAllowedForStatus(code)
がfalse
の場合でも、Content-Type
がsuppressedHeaders
によって抑制されない限り、レスポンスヘッダーに残るようになります。 -
テストケースの追加:
src/pkg/net/http/serve_test.go
にTestContentTypeOkayOn204
という新しいテストケースが追加されました。このテストは、HTTP 204 レスポンスに対してContent-Type
ヘッダーが正しく含まれ、Content-Length
ヘッダーが抑制されることを検証します。これにより、意図した動作が保証されます。
この変更は、HTTP仕様の解釈をより正確に反映し、Goの net/http
パッケージの堅牢性と柔軟性を向上させるものです。
コアとなるコードの変更箇所
src/pkg/net/http/serve_test.go
:TestContentTypeOkayOn204
という新しいテスト関数が追加されました。このテストは、204 レスポンスでContent-Type
ヘッダーが設定され、Content-Length
ヘッダーが抑制されることを確認します。
src/pkg/net/http/server.go
:writeHeader
関数内のヘッダー抑制ロジックが変更されました。以前はbodyAllowedForStatus
に基づいて一律にContent-Type
などが削除されていましたが、新しいsuppressedHeaders
関数を使用して、ステータスコードに応じた適切なヘッダーのみを削除するように修正されました。
src/pkg/net/http/transfer.go
:suppressedHeaders304
とsuppressedHeadersNoBody
という2つの文字列スライス変数が追加されました。これらはそれぞれ、304 レスポンスとボディを持たない他のレスポンス(204など)で抑制されるべきヘッダーのリストを定義します。suppressedHeaders(status int) []string
という新しい関数が追加されました。この関数は、与えられたステータスコードに基づいて、どのヘッダーを抑制すべきかを決定し、対応するヘッダー名のスライスを返します。
コアとなるコードの解説
-
src/pkg/net/http/serve_test.go
の変更:TestContentTypeOkayOn204
テストは、このコミットが修正しようとしている問題を直接検証します。ハンドラ内でContent-Length
とContent-Type
を設定し、204 ステータスコードを返します。その後、レスポンスを解析し、Content-Type
が存在し、Content-Length
が存在しないことをアサートします。これにより、変更が正しく機能していることが保証されます。 -
src/pkg/net/http/server.go
の変更:writeHeader
関数は、HTTPレスポンスのヘッダーを実際に書き込むGoのHTTPサーバーの中核部分です。この変更により、ヘッダーの抑制ロジックがより洗練され、HTTP仕様のニュアンス(特に304と204の違い)を正確に反映するようになりました。以前はContent-Type
が不必要に削除されていましたが、この修正により、204 レスポンスではContent-Type
が保持されるようになります。 -
src/pkg/net/http/transfer.go
の変更:suppressedHeaders
関数は、ヘッダー抑制のポリシーをカプセル化します。これにより、server.go
のwriteHeader
関数は、どのヘッダーを削除すべきかという詳細なロジックから解放され、よりクリーンなコードになります。suppressedHeaders304
とsuppressedHeadersNoBody
の導入は、異なるステータスコードに対する異なるヘッダー抑制ルールを明確に定義し、コードの可読性と保守性を向上させます。
これらの変更は全体として、Goの net/http
パッケージがHTTP仕様に準拠しつつ、より柔軟なヘッダー処理を可能にすることを目指しています。
関連リンク
- Go Change List (CL) for this commit: https://golang.org/cl/92400047
- 関連する以前のIssue (Issue 6685): このコミットメッセージで参照されていますが、直接的なGoのIssueトラッカー上のリンクは見つかりませんでした。しかし、
Content-Length
の修正に関連するものであったことが示唆されています。
参考にした情報源リンク
- RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1, Section 10.3.5 304 Not Modified: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
- HTTP 204 No Content Status Code: 一般的なHTTP仕様に関する情報源 (例: MDN Web Docsなど)
- Go言語の
net/http
パッケージのドキュメント (Go公式ドキュメント) - Web検索結果: "HTTP 204 response Content-Type", "golang issue 6685"