[インデックス 17406] ファイルの概要
このコミットは、Go言語の標準ライブラリ net/http
パッケージにおける Request.Body
フィールドのドキュメンテーションを改善するものです。特に、クライアントリクエストとサーバーリクエストにおける Request.Body
の振る舞いの違いについて、より明確な説明が追加されています。
コミット
commit 2ede818ae0761fc57dc1b52b4c8673933a3ff3fa
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Aug 27 16:13:21 2013 -0700
net/http: document Request.Body more
Fixes #6221
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/13289043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2ede818ae0761fc57dc1b52b4c8673933a3ff3fa
元コミット内容
net/http: document Request.Body more
Fixes #6221
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/13289043
変更の背景
この変更は、GoのIssue #6221「net/http: document Request.Body more clearly」に対応するものです。このIssueでは、net/http.Request
構造体の Body
フィールドに関するドキュメンテーションが不十分であり、特にクライアント側とサーバー側での Body
の扱いについて混乱が生じやすいという点が指摘されていました。
具体的には、以下のような疑問や問題がユーザーから提起されていました。
- クライアントが
http.NewRequest
でリクエストを作成する際、Body
をnil
に設定した場合と、空のio.ReadCloser
を設定した場合の挙動の違い。 - サーバー側で受信したリクエストの
Body
が、ボディがない場合でもnil
ではないこと。 Request.Body
をいつ、誰がクローズすべきかという責任の所在。
これらの不明瞭さが原因で、ユーザーが net/http
パッケージを正しく利用する上で誤解やバグを生む可能性がありました。このコミットは、これらの混乱を解消し、Request.Body
の利用方法をより明確にするために、既存のコメントを拡張することを目的としています。
前提知識の解説
Go言語の net/http
パッケージ
net/http
パッケージは、Go言語におけるHTTPクライアントおよびサーバーの実装を提供します。このパッケージは、Webアプリケーションの構築やHTTPリクエストの送信に不可欠な機能を提供します。
http.Request
構造体: HTTPリクエストを表す構造体です。リクエストメソッド(GET, POSTなど)、URL、ヘッダー、そしてリクエストボディなどの情報を含みます。http.Response
構造体: HTTPレスポンスを表す構造体です。ステータスコード、ヘッダー、レスポンスボディなどの情報を含みます。http.Handler
インターフェース: HTTPリクエストを処理するためのインターフェースで、ServeHTTP(ResponseWriter, *Request)
メソッドを実装します。HTTPサーバーは、このインターフェースを実装したハンドラを呼び出すことでリクエストを処理します。
io.ReadCloser
インターフェース
io.ReadCloser
は、Go言語の標準ライブラリ io
パッケージで定義されているインターフェースです。これは以下の2つのインターフェースを組み合わせたものです。
io.Reader
:Read(p []byte) (n int, err error)
メソッドを持ち、バイト列を読み出す機能を提供します。io.Closer
:Close() error
メソッドを持ち、リソースをクローズする機能を提供します。
HTTPリクエストやレスポンスのボディは、ストリームとして扱われるため、io.ReadCloser
型で表現されます。これにより、ボディの内容を効率的に読み出し、読み出しが完了した後にリソースを適切に解放(クローズ)することができます。
HTTPリクエストボディの特性
HTTPリクエストボディは、POSTやPUTなどのリクエストメソッドでデータをサーバーに送信する際に使用されます。その特性として、以下の点が挙げられます。
- ストリーム: ボディは通常、一度しか読み出せないストリームとして扱われます。これは、大きなデータを効率的に処理するためです。
- Content-Length: リクエストボディの長さは、
Content-Length
ヘッダーで示されることがあります。これにより、サーバーはボディの終端を事前に知ることができます。 - チャンク転送エンコーディング:
Content-Length
が不明な場合、ボディはチャンク転送エンコーディング(Chunked Transfer Encoding)を使用して送信されることがあります。この場合、ボディは複数のチャンクに分割され、各チャンクの前にそのサイズが記述されます。
技術的詳細
このコミットの技術的詳細は、net/http.Request
構造体の Body
フィールドに対するコメントの追加と修正に集約されます。変更前は、Body
フィールドのコメントは非常に簡潔で、「The message body.」としか記述されていませんでした。この簡潔さが、前述の混乱の原因となっていました。
変更後のコメントは、以下の重要な点を明確にしています。
Body
はリクエストのボディであること: これは基本的な説明ですが、改めて明記されています。- クライアントリクエストの場合:
nil
のBody
は、リクエストにボディがないことを意味します(例: GETリクエスト)。これは、http.NewRequest
でBody
引数にnil
を渡した場合に該当します。- HTTPクライアントの
Transport
(通常はhttp.DefaultTransport
) がBody
のClose
メソッドを呼び出す責任を負います。これは、ユーザーが明示的にBody.Close()
を呼び出す必要がないことを意味し、リソースリークを防ぐ上で重要です。
- サーバーリクエストの場合:
Request.Body
は常にnil
ではありません。たとえリクエストにボディがなくても、Body
フィールドはio.ReadCloser
のインスタンスとして存在します。この場合、Read
メソッドを呼び出すとすぐにEOF
(End Of File) が返されます。- サーバー(
http.Server
)がリクエストボディをクローズする責任を負います。 ServeHTTP
ハンドラ内でRequest.Body.Close()
を呼び出す必要はありません。これは、ハンドラがリクエスト処理を終えた後にサーバーが自動的にクローズするためです。
これらの詳細な説明により、開発者は Request.Body
を扱う際に、クライアントとサーバーのどちらのコンテキストにいるのかを意識し、適切な方法でボディを読み込み、リソースを管理できるようになります。特に、Close
メソッドの呼び出し責任が明確になったことで、リソースリークの可能性が低減されます。
コアとなるコードの変更箇所
変更は src/pkg/net/http/request.go
ファイルの Request
構造体内の Body
フィールドのコメントに限定されています。
--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -105,7 +105,16 @@ type Request struct {
// following a hyphen uppercase and the rest lowercase.
Header Header
- // The message body.
+ // Body is the request's body.
+ //
+ // For client requests, a nil body means the request has no
+ // body, such as a GET request. The HTTP Client's Transport
+ // is responsible for calling the Close method.
+ //
+ // For server requests, the Request Body is always non-nil
+ // but will return EOF immediately when no body is present.
+ // The Server will close the request body. The ServeHTTP
+ // Handler does not need to.
Body io.ReadCloser
// ContentLength records the length of the associated content.
コアとなるコードの解説
このコミットは、Go言語の net/http
パッケージにおける Request
構造体の Body
フィールドのドキュメンテーションを改善するものです。コードの機能的な変更は一切なく、既存のコメントがより詳細かつ明確になるように修正されています。
具体的には、Body io.ReadCloser
の行の直前にあるコメントブロックが以下のように変更されました。
変更前:
// The message body.
Body io.ReadCloser
変更後:
// Body is the request's body.
//
// For client requests, a nil body means the request has no
// body, such as a GET request. The HTTP Client's Transport
// is responsible for calling the Close method.
//
// For server requests, the Request Body is always non-nil
// but will return EOF immediately when no body is present.
// The Server will close the request body. The ServeHTTP
// Handler does not need to.
Body io.ReadCloser
この変更により、Request.Body
の振る舞いに関する重要な情報が、コードの利用者に直接提供されるようになりました。特に、クライアントとサーバーのコンテキストにおける Body
の nil
状態と Close
責任の明確化は、このフィールドを安全かつ効率的に利用するために不可欠な情報です。これは、Goのドキュメンテーションが、単なるAPIリファレンスではなく、利用者が陥りやすい落とし穴やベストプラクティスを説明する役割も担っていることを示しています。
関連リンク
- Go Issue #6221: net/http: document Request.Body more clearly
- Go CL 13289043: net/http: document Request.Body more
参考にした情報源リンク
- Go言語の
net/http
パッケージのドキュメンテーション: https://pkg.go.dev/net/http - Go言語の
io
パッケージのドキュメンテーション: https://pkg.go.dev/io - HTTP/1.1 仕様 (RFC 2616, 特にセクション 4.3 Message Body and Entity-Body): https://www.rfc-editor.org/rfc/rfc2616#section-4.3
- HTTP/1.1 仕様 (RFC 2616, 特にセクション 3.6.1 Chunked Transfer Coding): https://www.rfc-editor.org/rfc/rfc2616#section-3.6.1
- Go言語のソースコード (net/http/request.go): https://github.com/golang/go/blob/master/src/net/http/request.go
- Go言語のIssueトラッカー: https://github.com/golang/go/issues
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/