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

[インデックス 14780] ファイルの概要

このコミットは、Go言語の標準ライブラリである net/http パッケージ内の Request 構造体の URL フィールドに関するドキュメントを追加するものです。これにより、Request.URL がどのように生成され、どのフィールドが通常設定されるかについての誤解を解消し、開発者がより正確にこのフィールドを扱えるようにすることを目的としています。

コミット

commit 948f0b7a0bf2030bd927ccab7446324ed684d43f
Author: Rick Arnold <rickarnoldjr@gmail.com>
Date:   Wed Jan 2 17:37:27 2013 -0500

    net/http: document Request.URL
    
    Request.URL had no documentation before and some people were expecting all fields to be populated.
    
    Fixes #3805.
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/7008046

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/948f0b7a0bf2030bd927ccab7446324ed684d43f

元コミット内容

net/http: Request.URL のドキュメント化

Request.URL には以前ドキュメントがなく、一部の開発者はすべてのフィールドが設定されていると期待していました。

Fixes #3805.

変更の背景

このコミットの背景には、Go言語の net/http パッケージを使用する開発者からの http.Request 構造体内の URL フィールドに関する混乱がありました。具体的には、Request.URL フィールドが *url.URL 型であるにもかかわらず、HTTPリクエストの「Request-Line」から生成されるURLの特性上、SchemeHost といった一部のフィールドが空になることが一般的でした。しかし、この挙動が明示的にドキュメント化されていなかったため、開発者は URL オブジェクトのすべてのフィールドが常に完全にパースされ、設定されていると誤解し、予期せぬバグや混乱を招く可能性がありました。

この問題は、GoのIssueトラッカーで #3805 として報告されており、このコミットはその問題を解決するために Request.URL フィールドに明確なドキュメントを追加することを目的としています。ドキュメントを追加することで、開発者が Request.URL の実際の挙動を理解し、適切にコードを記述できるようになります。

前提知識の解説

このコミットを理解するためには、以下の概念について基本的な知識が必要です。

  1. Go言語の net/http パッケージ: Go言語の標準ライブラリであり、HTTPクライアントとサーバーの実装を提供します。WebアプリケーションやAPIサーバーを構築する際に中心的に使用されます。

    • http.Request 構造体: HTTPリクエストを表す構造体です。リクエストメソッド、URL、ヘッダー、ボディなどの情報を含みます。
    • http.ResponseWriter インターフェース: HTTPレスポンスを書き込むためのインターフェースです。
  2. Go言語の net/url パッケージ: URLのパースと生成を扱うためのパッケージです。

    • url.URL 構造体: URLの各コンポーネント(スキーム、ホスト、パス、クエリなど)を保持する構造体です。
  3. HTTP/1.1 の Request-Line (RFC 2616, Section 5.1): HTTPリクエストの最初の行は「Request-Line」と呼ばれ、以下の形式を持ちます。 Method SP Request-URI SP HTTP-Version CRLF ここで重要なのは Request-URI です。Request-URI は、リクエストのターゲットを識別するものであり、その形式はリクエストの種類によって異なります。

    • absoluteURI: 完全なURI(例: http://www.example.com/path?query)。プロキシリクエストなどで使用されます。
    • abs_path: パスとオプションのクエリ文字列(例: /path/to/resource?query=value)。最も一般的な形式で、オリジンサーバーへのリクエストで使用されます。
    • authority: ホストとポート(例: www.example.com:80)。CONNECT メソッドで使用されます。
    • *: オプションリクエスト(例: OPTIONS * HTTP/1.1)。

    このコミットで特に言及されているのは、abs_path 形式の Request-URI が使用される場合です。この場合、Request-URI にはスキームやホストの情報が含まれないため、http.Request.URL がパースされた際に、SchemeHost フィールドが空になるのが自然な挙動となります。

  4. Go言語のドキュメンテーション規約: Goでは、エクスポートされた(大文字で始まる)識別子(変数、関数、構造体、フィールドなど)の直前に書かれたコメントが、その識別子のドキュメントとして扱われます。godoc ツールやGoの公式ドキュメントサイトでこれらのドキュメントが参照されます。

技術的詳細

このコミットの技術的な核心は、http.Request 構造体の URL フィールドの挙動に関する明確な説明をコードコメントとして追加することです。

http.Request 構造体は、受信したHTTPリクエストを表現するために使用されます。その中の URL フィールドは *url.URL 型であり、リクエストされたURIをパースした結果を保持します。しかし、HTTP/1.1の仕様(RFC 2616)では、クライアントがオリジンサーバーに直接リクエストを送信する場合、Request-Lineの Request-URI は通常 abs_path 形式(例: /path/to/resource?query=value)を使用します。この形式にはスキーム(http://https://)やホスト名が含まれません。

Goの net/http パッケージは、この Request-URI を基に Request.URL フィールドを生成します。そのため、abs_path 形式のリクエストの場合、Request.URLSchemeHost フィールドは空になります。これは仕様に準拠した正しい挙動ですが、url.URL 構造体が完全なURLのすべてのコンポーネントを持つことができるため、開発者は Request.URL のすべてのフィールドが常に設定されていると誤解しがちでした。

このコミットでは、以下のコメントを追加することで、この誤解を解消します。

// URL is created from the URI supplied on the Request-Line
// as stored in RequestURI.
//
// For most requests, fields other than Path and RawQuery
// will be empty. (See RFC 2616, Section 5.1.2)
URL *url.URL

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

  • URL の生成元: Request.URLRequest-Line に含まれる RequestURI から生成されること。
  • 一般的なフィールドの空性: ほとんどのリクエストにおいて、PathRawQuery 以外のフィールド(例: Scheme, Host, User, Opaque, Fragment)は空になること。
  • RFC 2616, Section 5.1.2 への参照: この挙動がHTTP/1.1の仕様(特にRequest-URIの形式に関するセクション)に基づいていることを明示することで、開発者がさらに詳細な情報を参照できるようにしています。

これにより、開発者は Request.URL を扱う際に、どのフィールドが信頼できるか、どのフィールドが空になり得るかを事前に理解できるようになり、より堅牢なコードを書くことができます。

コアとなるコードの変更箇所

変更は src/pkg/net/http/request.go ファイルの Request 構造体内の URL フィールドの定義部分に集中しています。

--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -71,7 +71,13 @@ var reqWriteExcludeHeader = map[string]bool{\
 // or to be sent by a client.
 type Request struct {
  	Method string // GET, POST, PUT, etc.
-	URL    *url.URL
+
+	// URL is created from the URI supplied on the Request-Line
+	// as stored in RequestURI.
+	//
+	// For most requests, fields other than Path and RawQuery
+	// will be empty. (See RFC 2616, Section 5.1.2)
+	URL *url.URL
  
  	// The protocol version for incoming requests.
  	// Outgoing requests always use HTTP/1.1.

具体的には、URL *url.URL の行の直前に、6行のコメントが追加されています。元の1行のコメントが削除され、新しい複数行のコメントに置き換えられています。

コアとなるコードの解説

追加されたコメントは、http.Request 構造体の URL フィールドのセマンティクスを明確にしています。

// URL is created from the URI supplied on the Request-Line
// as stored in RequestURI.

この行は、Request.URL がHTTPリクエストの「Request-Line」に含まれるURI(RequestURI フィールドに格納されているもの)から生成されることを説明しています。これは、サーバーが受信した生のリクエストURIをパースして url.URL オブジェクトに変換することを示唆しています。

// For most requests, fields other than Path and RawQuery
// will be empty. (See RFC 2616, Section 5.1.2)

この重要な部分は、Request.URLPathRawQuery フィールド以外のほとんどのフィールド(例: Scheme, Host, User, Opaque, Fragment)が、一般的なリクエストでは空になることを明示しています。これは、HTTP/1.1の仕様(RFC 2616, Section 5.1.2)で定義されている Request-URIabs_path 形式(例: /path/to/resource?query=value)が、スキームやホスト名を含まないためです。このコメントにより、開発者は Request.URL を利用する際に、どのフィールドが常に利用可能であるかを正確に理解し、不必要なエラーハンドリングや誤った期待を避けることができます。

このドキュメントの追加は、Goの net/http パッケージの使いやすさと堅牢性を向上させる上で非常に重要です。

関連リンク

参考にした情報源リンク