[インデックス 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"