[インデックス 14553] ファイルの概要
このコミットは、Go言語の標準ライブラリである net/http
パッケージと net/url
パッケージにおける Host
フィールドのドキュメントを明確化し、関連するテストを追加するものです。具体的には、Request.Host
および URL.Host
フィールドがポート番号を含む可能性があることを明示することで、開発者の誤解を防ぎ、より堅牢なコード記述を促進します。
コミット
commit add1bed735e190abb03943a73e415576de211245
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Dec 4 07:09:01 2012 -0800
net/http: clarify that Request.Host may contain a port number
Fixes #4172
R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/6872055
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/add1bed735e190abb03943a73e415576de211245
元コミット内容
net/http: clarify that Request.Host may contain a port number
このコミットは、net/http
パッケージの Request.Host
フィールドがポート番号を含む可能性があることを明確にするものです。また、関連するテストが追加されています。
変更の背景
この変更の背景には、net/http.Request
構造体の Host
フィールドの挙動に関する開発者の誤解があったと考えられます。HTTP/1.1 の仕様である RFC 2616 では、Host
ヘッダはホスト名とオプションでポート番号を含むことができると定義されています。しかし、Goの net/http
パッケージの Request.Host
フィールドのドキュメントには、この「ポート番号を含む可能性がある」という点が明示されていませんでした。
これにより、開発者が Request.Host
を利用する際に、ポート番号が含まれている可能性を考慮せずにホスト名のみを期待し、パースエラーや予期せぬ挙動を引き起こす可能性がありました。例えば、Host
フィールドからポート番号を分離せずに直接データベース接続文字列や他のURLを構築しようとすると、問題が発生する可能性があります。
このコミットは、このような潜在的な問題を解消し、Request.Host
フィールドの正確な挙動を開発者に伝えることを目的としています。コミットメッセージにある "Fixes #4172" は、この曖昧さが原因で報告されたバグや問題に対応するものであることを示唆しています。
前提知識の解説
HTTP Host ヘッダ (RFC 2616)
HTTP/1.1 (RFC 2616) において、Host
ヘッダはリクエストされたリソースのインターネットホストとポート番号を指定するために使用されます。これは、単一のIPアドレスで複数のウェブサイトをホストするバーチャルホスティングにおいて特に重要です。
Host
ヘッダの一般的な形式は以下の通りです。
Host: <host>:<port>
ここで、<host>
はホスト名またはIPアドレスであり、<port>
はオプションのポート番号です。ポート番号が省略された場合、HTTPのデフォルトポートである80番が使用されたと見なされます。
Go言語の net/http.Request
構造体
Go言語の net/http
パッケージは、HTTPクライアントとサーバーの実装を提供します。http.Request
構造体は、受信したHTTPリクエストを表し、その中にリクエストに関する様々な情報が含まれています。
Request
構造体には Host
フィールドがあり、これはHTTPリクエストの Host
ヘッダの値、またはリクエストURL自体から抽出されたホスト名(とポート番号)を格納します。このフィールドは、サーバーがどのバーチャルホストに対するリクエストであるかを判断するために使用されます。
Go言語の net/url.URL
構造体
Go言語の net/url
パッケージは、URLのパースと生成のための機能を提供します。url.URL
構造体は、パースされたURLの各コンポーネント(スキーム、ホスト、パス、クエリなど)を保持します。
URL
構造体にも Host
フィールドがあり、これはURLのホスト部分(ホスト名とオプションでポート番号)を格納します。
これらの Host
フィールドがポート番号を含む可能性があるという点は、特にネットワークプログラミングにおいて重要であり、このコミットはそれを明確にすることで、開発者がより正確なコードを書けるように支援します。
技術的詳細
このコミットは、主にGo言語の標準ライブラリ内の2つのファイル、src/pkg/net/http/request.go
と src/pkg/net/url/url.go
のドキュメント文字列に修正を加えています。加えて、src/pkg/net/http/request_test.go
に新しいテストケースが追加され、Request.Host
の挙動が期待通りであることを検証しています。
ドキュメントの明確化
-
src/pkg/net/http/request.go
:Request
構造体のHost
フィールドのコメントに// It may be of the form "host:port".
という行が追加されました。これにより、Host
フィールドがホスト名だけでなく、ポート番号も含むhost:port
形式である可能性があることが明示されました。 -
src/pkg/net/url/url.go
:URL
構造体のHost
フィールドのコメントがHost string
からHost string // host or host:port
に変更されました。これも同様に、URL.Host
フィールドがhost
またはhost:port
の形式を取りうることを明確にしています。
これらのドキュメントの変更は、コードの動作自体を変更するものではなく、APIの利用者がフィールドの正確な内容を理解し、それに応じてコードを記述できるようにするためのものです。これにより、Host
フィールドからポート番号を適切に分離するなどの処理が必要な場合に、開発者がその必要性を認識しやすくなります。
テストケースの追加
-
src/pkg/net/http/request_test.go
:TestNewRequestHost
という新しいテスト関数が追加されました。このテストは、NewRequest
関数を使用してhttp://localhost:1234/
というURLでリクエストを作成し、その結果生成されるRequest
オブジェクトのHost
フィールドが期待通り"localhost:1234"
であることを検証します。このテストの追加は非常に重要です。ドキュメントの変更が意図した通りの挙動を反映していることを保証するだけでなく、将来的なリファクタリングや変更があった際に、
Request.Host
の挙動が意図せず変更されないようにするための回帰テストとしても機能します。これは、Go言語のテスト駆動開発(TDD)や堅牢なソフトウェア開発のプラクティスに沿ったものです。
これらの変更は全体として、GoのネットワークライブラリのAPIの明確性を向上させ、開発者がより正確でバグの少ないコードを書くための支援となります。
コアとなるコードの変更箇所
変更されたファイルと行数は以下の通りです。
src/pkg/net/http/request.go
: 1行追加src/pkg/net/http/request_test.go
: 10行追加src/pkg/net/url/url.go
: 2行変更 (1行追加, 1行削除)
src/pkg/net/http/request.go
--- a/src/pkg/net/http/request.go
+++ b/src/pkg/net/http/request.go
@@ -124,6 +124,7 @@ type Request struct {
// The host on which the URL is sought.
// Per RFC 2616, this is either the value of the Host: header
// or the host name given in the URL itself.
+ // It may be of the form "host:port".
Host string
// Form contains the parsed form data, including both the URL
src/pkg/net/http/request_test.go
--- a/src/pkg/net/http/request_test.go
+++ b/src/pkg/net/http/request_test.go
@@ -228,6 +228,16 @@ func TestReadRequestErrors(t *testing.T) {
}
}
+func TestNewRequestHost(t *testing.T) {
+ req, err := NewRequest("GET", "http://localhost:1234/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if req.Host != "localhost:1234" {
+ t.Errorf("Host = %q; want localhost:1234", req.Host)
+ }
+}
+
func testMissingFile(t *testing.T, req *Request) {
f, fh, err := req.FormFile("missing")
if f != nil {
src/pkg/net/url/url.go
--- a/src/pkg/net/url/url.go
+++ b/src/pkg/net/url/url.go
@@ -224,7 +224,7 @@ type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
- Host string
+ Host string // host or host:port
Path string
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
コアとなるコードの解説
src/pkg/net/http/request.go
の変更
Request
構造体の Host
フィールドのコメントに // It may be of the form "host:port".
という行が追加されました。これは、Host
フィールドが単なるホスト名だけでなく、ホスト名:ポート番号
の形式でポート番号を含む可能性があることを明示しています。
この変更は、Host
フィールドの値を処理する開発者にとって非常に重要です。例えば、Host
フィールドからホスト名とポート番号を分離する必要がある場合(例: データベース接続文字列の構築、特定のポートへのルーティングなど)、このコメントは開発者にその必要性を認識させ、適切なパース処理(例: net.SplitHostPort
関数などを使用)を促します。これにより、ポート番号が含まれている場合に発生しうる潜在的なバグを防ぐことができます。
src/pkg/net/http/request_test.go
の変更
TestNewRequestHost
という新しいテスト関数が追加されました。このテストは以下の手順を実行します。
NewRequest("GET", "http://localhost:1234/", nil)
を呼び出して、ポート番号を含むURLを持つHTTPリクエストを作成します。- エラーが発生した場合は、テストを失敗させます。
- 作成されたリクエストの
req.Host
フィールドが"localhost:1234"
と等しいかどうかを検証します。もし等しくなければ、エラーメッセージを出力してテストを失敗させます。
このテストの追加は、Request.Host
フィールドが実際にポート番号を正しく保持することを確認するためのものです。これは、ドキュメントの変更が単なる説明だけでなく、実際の挙動と一致していることを保証する「実行可能なドキュメント」としての役割も果たします。また、将来的に NewRequest
関数や関連するパースロジックが変更された際に、このテストが回帰テストとして機能し、意図しない挙動の変更を早期に検出するのに役立ちます。
src/pkg/net/url/url.go
の変更
URL
構造体の Host
フィールドのコメントが Host string
から Host string // host or host:port
に変更されました。
この変更は、net/url
パッケージの URL
構造体における Host
フィールドも、net/http.Request
の Host
フィールドと同様に、ホスト名とポート番号の両方を含む可能性があることを明確にしています。net/http
パッケージは内部的に net/url
パッケージを利用しているため、両方のドキュメントを整合させることは、Goの標準ライブラリ全体の一貫性を保つ上で重要です。これにより、URLを扱う開発者が Host
フィールドの正確な形式を理解し、適切な処理を行うことができます。
これらの変更は、Go言語のAPIの使いやすさと堅牢性を向上させるための、小さくも重要な改善です。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/add1bed735e190abb03943a73e415576de211245
- Go Code Review (CL): https://golang.org/cl/6872055
参考にした情報源リンク
- RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23 (Host Header Field)
- Go
net/http
パッケージドキュメント: https://pkg.go.dev/net/http - Go
net/url
パッケージドキュメント: https://pkg.go.dev/net/url - Go
net
パッケージドキュメント (SplitHostPort): https://pkg.go.dev/net#SplitHostPort