Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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 でリクエストを作成する際、Bodynil に設定した場合と、空の 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.」としか記述されていませんでした。この簡潔さが、前述の混乱の原因となっていました。

変更後のコメントは、以下の重要な点を明確にしています。

  1. Body はリクエストのボディであること: これは基本的な説明ですが、改めて明記されています。
  2. クライアントリクエストの場合:
    • nilBody は、リクエストにボディがないことを意味します(例: GETリクエスト)。これは、http.NewRequestBody 引数に nil を渡した場合に該当します。
    • HTTPクライアントの Transport (通常は http.DefaultTransport) が BodyClose メソッドを呼び出す責任を負います。これは、ユーザーが明示的に Body.Close() を呼び出す必要がないことを意味し、リソースリークを防ぐ上で重要です。
  3. サーバーリクエストの場合:
    • 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 の振る舞いに関する重要な情報が、コードの利用者に直接提供されるようになりました。特に、クライアントとサーバーのコンテキストにおける Bodynil 状態と Close 責任の明確化は、このフィールドを安全かつ効率的に利用するために不可欠な情報です。これは、Goのドキュメンテーションが、単なるAPIリファレンスではなく、利用者が陥りやすい落とし穴やベストプラクティスを説明する役割も担っていることを示しています。

関連リンク

参考にした情報源リンク