[インデックス 11825] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet/http
パッケージにおけるhttp.ResponseWriter
インターフェースのWrite
メソッドと、net/http/sniff
パッケージのDetectContentType
関数のドキュメントを改善するものです。具体的には、Write
メソッドがContent-Type
ヘッダが設定されていない場合にDetectContentType
を使用してコンテンツタイプを自動検出する挙動と、DetectContentType
関数の動作(特にスニッフィングのバイト数と戻り値の保証)について、より明確な説明を追加しています。
コミット
commit d9da346078f4b2887c26c55cdd162b15bf8bfcc6
Author: Russ Cox <rsc@golang.org>
Date: Sun Feb 12 23:14:48 2012 -0500
net/http: document use of DetectContentType
Fixes #2365.
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5653070
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/d9da346078f4b2887c26c55cdd162b15bf8bfcc6
元コミット内容
net/http: document use of DetectContentType
Fixes #2365.
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/5653070
変更の背景
このコミットは、GoのIssue #2365を修正するために行われました。Issue #2365は、net/http
パッケージのhttp.ResponseWriter
インターフェースのWrite
メソッドが、Content-Type
ヘッダが明示的に設定されていない場合に、内部的にDetectContentType
関数を使用してコンテンツタイプを自動的に推測するという重要な挙動について、ドキュメントに記載がないことを指摘していました。
開発者がhttp.ResponseWriter
を使用してHTTPレスポンスを書き込む際、Content-Type
ヘッダを設定し忘れることはよくあります。このような場合、Webブラウザやクライアントはレスポンスボディの内容に基づいてコンテンツタイプを推測しようとしますが、これはセキュリティ上の問題(MIMEタイプスニッフィング攻撃など)や、意図しないレンダリングを引き起こす可能性があります。Goのnet/http
パッケージは、この問題を緩和するために、Write
メソッドが最初の512バイトのデータに基づいてコンテンツタイプを自動的に検出する機能を提供していました。しかし、この挙動がドキュメントに明記されていなかったため、開発者はこの自動検出機能の存在やその詳細を知ることができず、予期せぬ動作に遭遇したり、適切なContent-Type
ヘッダの設定を怠ったりする可能性がありました。
このコミットは、この重要な自動検出の挙動をhttp.ResponseWriter.Write
のドキュメントに追加することで、開発者がより安全で予測可能なHTTPサービスを構築できるようにすることを目的としています。また、DetectContentType
関数のドキュメントも改善され、その動作原理(スニッフィングのバイト数、常に有効なMIMEタイプを返すこと)がより明確に説明されています。
前提知識の解説
Content-Type (MIMEタイプ)
Content-Type
は、HTTPヘッダの一つで、HTTPメッセージのボディに含まれるデータのメディアタイプ(MIMEタイプ)を示すものです。例えば、text/html
はHTMLドキュメント、application/json
はJSONデータ、image/png
はPNG画像を表します。クライアント(Webブラウザなど)は、このContent-Type
ヘッダを見て、受信したデータをどのように解釈し、表示すべきかを判断します。
MIMEタイプスニッフィング (MIME Type Sniffing)
MIMEタイプスニッフィングとは、HTTPレスポンスにContent-Type
ヘッダがない場合や、ヘッダが不正確な場合に、Webブラウザなどのクライアントがレスポンスボディの先頭バイトを検査して、データの実際のコンテンツタイプを推測するプロセスです。これはユーザーエクスペリエンスを向上させるために導入されましたが、悪意のあるコンテンツが誤ったMIMEタイプで提供され、ブラウザがそれを実行可能なスクリプトとして解釈してしまうなど、セキュリティ上の脆弱性(MIMEタイプスニッフィング攻撃)を引き起こす可能性があります。
net/http
パッケージ (Go言語)
Go言語の標準ライブラリであるnet/http
パッケージは、HTTPクライアントとサーバーの実装を提供します。WebアプリケーションやAPIサーバーを構築する際に中心的に使用されます。
http.ResponseWriter
: HTTPレスポンスを構築するために使用されるインターフェースです。このインターフェースを通じて、HTTPヘッダの設定やレスポンスボディの書き込みが行われます。http.Request
: 受信したHTTPリクエストを表す構造体です。http.Handler
: HTTPリクエストを処理するためのインターフェースです。
DetectContentType
関数
DetectContentType
関数は、Goのnet/http/sniff
パッケージで提供されるユーティリティ関数です。この関数は、与えられたバイトスライス(通常はHTTPレスポンスボディの先頭部分)を分析し、その内容に基づいてMIMEタイプを推測します。この推測は、WHATWGのMIME Sniffing Standardに準拠しています。
技術的詳細
このコミットの技術的詳細は、主にGoのnet/http
パッケージにおけるHTTPレスポンスのContent-Type
ヘッダの自動設定メカニズムと、その基盤となるDetectContentType
関数の動作に関するドキュメントの改善にあります。
http.ResponseWriter.Write
の挙動
Goのnet/http
パッケージでは、http.ResponseWriter
インターフェースのWrite
メソッドが呼び出された際に、以下のようなロジックが内部的に実行されます。
- ヘッダの書き込み: もし
WriteHeader
メソッドがまだ呼び出されていない場合、Write
メソッドは自動的にWriteHeader(http.StatusOK)
を呼び出し、HTTPステータスコード200 OKでレスポンスヘッダを送信します。 Content-Type
の自動検出: ここがこのコミットの核心です。もしレスポンスヘッダにContent-Type
が明示的に設定されていない場合、Write
メソッドは書き込まれるデータの最初の512バイト(sniffLen
で定義される定数)をDetectContentType
関数に渡します。DetectContentType
が返したMIMEタイプが、レスポンスのContent-Type
ヘッダとして自動的に設定されます。この挙動は、開発者がContent-Type
を明示的に設定し忘れた場合でも、ある程度の適切なデフォルト値が提供されることを保証します。- データ書き込み: その後、与えられたデータがHTTP接続に書き込まれます。
この自動検出メカニズムは、WebブラウザのMIMEタイプスニッフィングと同様の原理に基づいていますが、サーバー側で制御されるため、より予測可能で安全な挙動を提供します。
DetectContentType
関数の動作
DetectContentType
関数は、WHATWGのMIME Sniffing Standard (http://mimesniff.spec.whatwg.org/) に従ってコンテンツタイプを検出します。
- スニッフィングのバイト数: この関数は、与えられたデータの最大512バイト(
sniffLen
)を検査してコンテンツタイプを決定します。データが512バイト未満の場合、利用可能なすべてのバイトが検査されます。 - 戻り値の保証:
DetectContentType
は、常に有効なMIMEタイプ文字列を返します。もしより具体的なMIMEタイプを決定できない場合(例えば、データが空であるか、既知のパターンに一致しない場合)、デフォルトのフォールバックとしてapplication/octet-stream
(汎用的なバイナリデータ)を返します。これにより、クライアントが常に何らかのContent-Type
情報を受け取ることが保証されます。
このコミットは、これらの重要な挙動をGoのドキュメントに明記することで、開発者がnet/http
パッケージの動作をより深く理解し、適切に利用できるようにすることを目的としています。特に、Content-Type
ヘッダの自動設定は、多くのWebアプリケーションで暗黙的に利用される機能であるため、その存在と動作原理を明確にすることは、予期せぬ挙動の回避やセキュリティの向上に寄与します。
コアとなるコードの変更箇所
このコミットでは、以下の2つのファイルが変更されています。
src/pkg/net/http/server.go
src/pkg/net/http/sniff.go
それぞれの変更箇所は以下の通りです。
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
index 8c4822ec74..fb3bc81756 100644
--- a/src/pkg/net/http/server.go
+++ b/src/pkg/net/http/server.go
@@ -59,7 +59,9 @@ type ResponseWriter interface {
// Write writes the data to the connection as part of an HTTP reply.
// If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
- // before writing the data.
+ // before writing the data. If the Header does not contain a
+ // Content-Type line, Write adds a Content-Type set to the result of passing
+ // the initial 512 bytes of written data to DetectContentType.
Write([]byte) (int, error)
// WriteHeader sends an HTTP response header with status code.
diff --git a/src/pkg/net/http/sniff.go b/src/pkg/net/http/sniff.go
index c1c78e2417..68f519b054 100644
--- a/src/pkg/net/http/sniff.go
+++ b/src/pkg/net/http/sniff.go
@@ -9,15 +9,15 @@ import (
"encoding/binary"
)
-// Content-type sniffing algorithm.
-// References in this file refer to this draft specification:
-// http://mimesniff.spec.whatwg.org/
-
-// The algorithm prefers to use sniffLen bytes to make its decision.
+// The algorithm uses at most sniffLen bytes to make its decision.
const sniffLen = 512
-// DetectContentType returns the sniffed Content-Type string
-// for the given data. This function always returns a valid MIME type.
+// DetectContentType implements the algorithm described
+// at http://mimesniff.spec.whatwg.org/ to determine the
+// Content-Type of the given data. It considers at most the
+// first 512 bytes of data. DetectContentType always returns
+// a valid MIME type: if it cannot determine a more specific one, it
+// returns "application/octet-stream".
func DetectContentType(data []byte) string {
if len(data) > sniffLen {
data = data[:sniffLen]
コアとなるコードの解説
src/pkg/net/http/server.go
の変更
http.ResponseWriter
インターフェースのWrite
メソッドのドキュメントに、以下の行が追加されました。
+ // before writing the data. If the Header does not contain a
+ // Content-Type line, Write adds a Content-Type set to the result of passing
+ // the initial 512 bytes of written data to DetectContentType.
この変更により、Write
メソッドがContent-Type
ヘッダが未設定の場合に、書き込まれるデータの最初の512バイトをDetectContentType
に渡し、その結果をContent-Type
として自動的に設定するという重要な挙動が明示されました。これにより、開発者はこの自動検出メカニズムの存在を認識し、必要に応じて明示的にContent-Type
を設定するか、この自動検出に依存するかを判断できるようになります。
src/pkg/net/http/sniff.go
の変更
DetectContentType
関数のドキュメントが大幅に改善されました。
変更前:
// Content-type sniffing algorithm.
// References in this file refer to this draft specification:
// http://mimesniff.spec.whatwg.org/
// The algorithm prefers to use sniffLen bytes to make its decision.
const sniffLen = 512
// DetectContentType returns the sniffed Content-Type string
// for the given data. This function always returns a valid MIME type.
func DetectContentType(data []byte) string {
変更後:
// The algorithm uses at most sniffLen bytes to make its decision.
const sniffLen = 512
// DetectContentType implements the algorithm described
// at http://mimesniff.spec.whatwg.org/ to determine the
// Content-Type of the given data. It considers at most the
// first 512 bytes of data. DetectContentType always returns
// a valid MIME type: if it cannot determine a more specific one, it
// returns "application/octet-stream".
func DetectContentType(data []byte) string {
この変更により、DetectContentType
関数の動作がより詳細かつ正確に説明されています。
- 標準への準拠:
DetectContentType
がWHATWGのMIME Sniffing Standard (http://mimesniff.spec.whatwg.org/) に従ってコンテンツタイプを決定することが明確に述べられています。 - スニッフィングのバイト数: 「It considers at most the first 512 bytes of data.」という記述により、最大512バイトのデータが考慮されることが強調されています。以前の「The algorithm prefers to use sniffLen bytes to make its decision.」よりも具体的です。
- 戻り値の保証: 「DetectContentType always returns a valid MIME type: if it cannot determine a more specific one, it returns "application/octet-stream".」という記述により、関数が常に有効なMIMEタイプを返し、より具体的なタイプを決定できない場合は
application/octet-stream
を返すことが明確に示されています。これは、関数の堅牢性と予測可能性を保証する重要な情報です。
これらのドキュメントの改善は、Goのnet/http
パッケージの透明性を高め、開発者がHTTPレスポンスのContent-Type
処理をより正確に理解し、制御できるようにするために非常に重要です。
関連リンク
- Go Issue #2365: https://github.com/golang/go/issues/2365 (このコミットが修正したIssue)
- Go Code Review (CL) 5653070: https://golang.org/cl/5653070 (このコミットに対応するGoのコードレビュー)
参考にした情報源リンク
- WHATWG MIME Sniffing Standard: https://mimesniff.spec.whatwg.org/ (MIMEタイプスニッフィングのアルゴリズムに関する標準仕様)
- HTTP Content-Type ヘッダ: https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Type (MDN Web DocsによるContent-Typeヘッダの解説)
- Go言語
net/http
パッケージドキュメント: https://pkg.go.dev/net/http (Go公式ドキュメント) - Go言語
net/http/sniff
パッケージドキュメント: https://pkg.go.dev/net/http/sniff (Go公式ドキュメント)