[インデックス 15455] ファイルの概要
このコミットは、Go言語の実験的な cookiejar
パッケージにおいて、canonicalHost
関数のエラー処理に関するテストを追加するものです。これにより、ホスト名の正規化処理における潜在的なエラーケースが適切に扱われることを保証し、クッキーの取り扱いにおける堅牢性を向上させます。
コミット
- コミットハッシュ: 15cce227c78ac2b499e9ad3c49ccb67d2f870169
- Author: Nigel Tao nigeltao@golang.org
- Date: Wed Feb 27 13:05:57 2013 +1100
- コミットメッセージ:
exp/cookiejar: add a test for canonicalHost errors. R=dr.volker.dobler CC=golang-dev https://golang.org/cl/7389048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/15cce227c78ac2b499e9ad3c49ccb67d2f870169
元コミット内容
exp/cookiejar: add a test for canonicalHost errors.
R=dr.volker.dobler
CC=golang-dev
https://golang.org/cl/7389048
変更の背景
net/http/cookiejar
パッケージ(当時は exp/cookiejar
として実験的に提供されていた)は、HTTPクッキーを管理するための重要なコンポーネントです。クッキーは特定のドメインに関連付けられており、そのドメインを正確に識別し、正規化するプロセスが不可欠です。この正規化は canonicalHost
関数によって行われます。
以前の canonicalHost
関数は、不正な形式のホスト名が入力された場合にエラーを返す可能性がありましたが、そのエラーがテストで適切に検証されていませんでした。このコミットの背景には、canonicalHost
関数がエラーを返すような不正な入力に対しても、cookiejar
が堅牢に動作することを保証する必要性がありました。特に、角括弧が不整合なIPv6アドレスのような、構文的に不正なホスト名が与えられた場合に、canonicalHost
がエラーを正しく報告し、そのエラーが適切に処理されることを確認するためのテストが不足していました。
この変更は、cookiejar
の信頼性とセキュリティを向上させるための重要なステップであり、RFC 6265(HTTP State Management Mechanism)などの関連する標準に準拠するために、ホスト名の正規化が正確かつエラー耐性を持つことが求められます。
前提知識の解説
exp/cookiejar
パッケージ (現在の net/http/cookiejar
)
net/http/cookiejar
パッケージは、Go言語の標準ライブラリの一部であり、HTTPクライアントがクッキーを保存、取得、管理するための機能を提供します。ウェブブラウザがクッキーを扱うのと同様に、HTTPリクエスト間で状態を維持するために使用されます。このパッケージは、RFC 6265(HTTP State Management Mechanism)に準拠しており、クッキーのドメインマッチング、パスマッチング、有効期限、セキュリティ属性(Secure, HttpOnlyなど)を適切に処理します。
canonicalHost
関数
canonicalHost
は、cookiejar
パッケージの内部で利用される非公開(unexported)関数です。その主な役割は、与えられたホスト名を正規化された形式に変換することです。正規化とは、例えば、ホスト名の大文字・小文字の区別をなくしたり、末尾のドットを削除したり、国際化ドメイン名(IDN)をPunycode形式に変換したりする処理を指します。これにより、クッキーがその関連ドメインと一貫して照合されることが保証されます。
例えば、www.example.com.
は www.example.com
に、www.bücher.de
は Punycode 形式の www.xn--bcher-kva.de
に正規化されます。IPv6アドレスも角括弧を含めて正規化されます。
ホスト名の正規化とRFC 6265
HTTPクッキーの仕様であるRFC 6265では、クッキーがどのドメインに属するかを厳密に定義しています。これには、ドメインマッチングのルールが含まれており、canonicalHost
のような正規化関数はこれらのルールを正確に適用するために不可欠です。正規化が不適切だと、クッキーが誤ったドメインに送信されたり、逆に本来受け取るべきクッキーを受け取れなかったりする可能性があります。また、PublicSuffixList
(golang.org/x/net/publicsuffix
パッケージで提供)と連携することで、悪意のあるサーバーがトップレベルドメイン(TLD)全体やパブリックサフィックスに対してクッキーを設定するようなセキュリティ脆弱性を防ぐ役割も果たします。
Go言語のテストフレームワーク
Go言語には、標準で軽量なテストフレームワークが組み込まれています。testing
パッケージを使用することで、ユニットテストやベンチマークテストを簡単に記述できます。テスト関数は Test
で始まり、*testing.T
型の引数を取ります。t.Errorf
はテストが失敗したことを報告し、エラーメッセージを出力するために使用されます。continue
はループの次のイテレーションに進むために使用されます。
技術的詳細
このコミットは、canonicalHost
関数がエラーを返すケースを明示的にテストに追加することで、cookiejar
の堅牢性を高めています。
canonicalHost
関数は、入力されたホスト名がRFC 6265の仕様に準拠しているか、または有効な形式であるかを検証し、正規化されたホスト名を返します。しかし、全ての入力が有効なホスト名であるとは限りません。例えば、"[bad.unmatched.bracket:"
のような、角括弧が閉じられていない不正なIPv6アドレス形式の文字列は、canonicalHost
が処理できない無効な入力です。このような場合、canonicalHost
はエラーを返すことが期待されます。
このコミットでは、jar_test.go
内の canonicalHostTests
マップに新しいエントリ "[bad.unmatched.bracket:": "error"
が追加されました。これは、"[bad.unmatched.bracket:"
という入力に対して canonicalHost
がエラーを返すことを期待するというテストケースを定義しています。
TestCanonicalHost
関数内では、各テストケースに対して canonicalHost
を呼び出し、その戻り値である got
(正規化されたホスト名)と err
(エラー)を検証します。
変更前は、canonicalHost
がエラーを返しても、そのエラーが適切にチェックされていませんでした(got, _ := canonicalHost(h)
のようにエラーが破棄されていた)。変更後は、err
変数を受け取り、want == "error"
の場合に err
が nil
でないことを確認し、それ以外の場合は err
が nil
であることを確認するロジックが追加されました。これにより、canonicalHost
がエラーを返すことが期待されるケースで実際にエラーが返されるか、またエラーが返されるべきでないケースでエラーが返されないか、という両方の側面がテストされるようになりました。
このテストの追加により、将来的に canonicalHost
の実装が変更された際に、不正な入力に対するエラー処理の挙動が意図せず変更されることを防ぎ、cookiejar
の安定性と信頼性を維持することができます。
コアとなるコードの変更箇所
変更は src/pkg/exp/cookiejar/jar_test.go
ファイルに集中しています。
--- a/src/pkg/exp/cookiejar/jar_test.go
+++ b/src/pkg/exp/cookiejar/jar_test.go
@@ -51,15 +51,26 @@ var canonicalHostTests = map[string]string{\n "[2001:4860:0:::68]:8080": "2001:4860:0:::68",\n "www.bücher.de": "www.xn--bcher-kva.de",\n "www.example.com.": "www.example.com",
+\t"[bad.unmatched.bracket:": "error",
}\n \n func TestCanonicalHost(t *testing.T) {\n \tfor h, want := range canonicalHostTests {\n-\t\tgot, _ := canonicalHost(h)\n+\t\tgot, err := canonicalHost(h)\n+\t\tif want == "error" {\n+\t\t\tif err == nil {\n+\t\t\t\tt.Errorf("%q: got nil error, want non-nil", h)\n+\t\t\t}\n+\t\t\tcontinue\n+\t\t}\n+\t\tif err != nil {\n+\t\t\tt.Errorf("%q: %v", h, err)\n+\t\t\tcontinue\n+\t\t}\n \t\tif got != want {\n \t\t\tt.Errorf("%q: got %q, want %q", h, got, want)\n+\t\t\tcontinue\n \t\t}\n-\t\t// TODO handle errors
\t}\n }\n \n```
## コアとなるコードの解説
1. **`canonicalHostTests` マップへの追加**:
```go
"[bad.unmatched.bracket:": "error",
```
`canonicalHostTests` は、`canonicalHost` 関数のテストケースを定義するマップです。キーは入力ホスト名、値は期待される正規化されたホスト名です。この行は、`"[bad.unmatched.bracket:"` という不正な形式のホスト名が入力された場合に、`canonicalHost` がエラーを返すことを期待するという新しいテストケースを追加しています。`"error"` という文字列は、このテストケースがエラーを期待していることを示すマーカーとして使用されます。
2. **`TestCanonicalHost` 関数の変更**:
```go
func TestCanonicalHost(t *testing.T) {
for h, want := range canonicalHostTests {
got, err := canonicalHost(h) // エラーも受け取るように変更
if want == "error" { // 期待値が"error"の場合
if err == nil { // エラーがnil(エラーが発生しなかった)場合
t.Errorf("%q: got nil error, want non-nil", h) // エラーを報告
}
continue // 次のテストケースへ
}
if err != nil { // エラーが発生した場合(ただし、"error"を期待していない場合)
t.Errorf("%q: %v", h, err) // エラーを報告
continue // 次のテストケースへ
}
if got != want { // 正規化されたホスト名が期待値と異なる場合
t.Errorf("%q: got %q, want %q", h, got, want) // エラーを報告
continue // 次のテストケースへ
}
// TODO handle errors (削除されたコメント)
}
}
```
- `got, err := canonicalHost(h)`: 以前はエラーを破棄していましたが、この変更により `canonicalHost` が返すエラーも `err` 変数で受け取るようになりました。
- `if want == "error"` ブロック:
- これは、現在のテストケースが `canonicalHost` からエラーが返されることを期待している場合に実行されます。
- `if err == nil`: もし `canonicalHost` がエラーを返さなかった(`err` が `nil`)場合、それは期待に反するため、`t.Errorf` を使ってテスト失敗を報告します。
- `continue`: エラーの有無のチェックが完了したら、このテストケースの残りの部分(正規化されたホスト名の比較)はスキップし、次のテストケースに進みます。
- `if err != nil` ブロック:
- これは、現在のテストケースがエラーを期待していないにもかかわらず、`canonicalHost` がエラーを返した場合に実行されます。
- `t.Errorf("%q: %v", h, err)`: エラーが発生したことを報告します。
- `continue`: エラーが発生したため、正規化されたホスト名の比較は意味がないので、次のテストケースに進みます。
- `if got != want` ブロック:
- これは、`canonicalHost` がエラーを返さず、かつエラーが期待されていない場合に実行されます。
- `t.Errorf("%q: got %q, want %q", h, got, want)`: 正規化されたホスト名 `got` が期待値 `want` と異なる場合にテスト失敗を報告します。
- `continue`: テスト失敗を報告したら、次のテストケースに進みます。
- `// TODO handle errors` コメントの削除: エラー処理が実装されたため、このTODOコメントは不要になりました。
これらの変更により、`canonicalHost` 関数が不正な入力に対して適切にエラーを返すかどうかが、より厳密にテストされるようになりました。
## 関連リンク
- Go CL (Code Review) 7389048: [https://golang.org/cl/7389048](https://golang.org/cl/7389048)
## 参考にした情報源リンク
- Go言語の `net/http/cookiejar` パッケージの `canonicalHost` 関数に関する情報:
- [https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHWJEOjcc6mPkU_bFAW2xQbGFQucqKtfeWhbSnec9QjYTkRchgqPC9hhjrbYYgcQX-u1Mh4qrFTExsAGpKD8LPndIlArLqM2kasCJDFpMCTrDOpWbrVUdEI5HbyppDPsBrsnWAkuQ8HW_e2iz0eBwsXrA==](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHWJEOjcc6mPkU_bFAW2xQbGFQucqKtfeWhbSnec9QjYTkRchgqPC9hhjrbYYgcQX-u1Mh4qrFTExsAGpKD8LPndIlArLqM2kasCJDFpMCTrDOpWbrVUdEI5HbyppDPsBrsnWAkuQ8HW_e2iz0eBwsXrA==)
- [https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH5d5NYyBzN2vHUUO7iytgtYQElrCB2FTSPpkqef7JGp-BTwklAZqDilu2wLrDAwm-y3jy5gunjgHIAVcB-G6kSpwppE61QP-jyNUWB-I3nCsoWPyDEZFJr3U5VqrQ3-N7QKF4qJvvjlAbxsXGvE6q0H6pxaf9HABQ0PA==](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQH5d5NYyBzN2vHUUO7iytgtYQElrCB2FTSPpkqef7JGp-BTwklAZqDilu2wLrDAwm-y3jy5gunjgHIAVcB-G6kSpwppE61QP-jyNUWB-I3nCsoWPyDEZFJr3U5VqrQ3-N7QKF4qJvvjlAbxsXGvE6q0H6pxaf9HABQ0PA==)
- [https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQENWlYbt9dcj9vuc9DjBqDH-deRV2kYVxD2RLGIzQBnCNsw_XOEEYWNhc23ZJyYcFaqsuyiy4DUEp5xFcs_eO_GNANkqD1IGUqUtUziBVC4l0aCAGCsKk8MgNjJgukp2aMKe3hk0uWFkp5-pA2kaJ1dnouPZ7DKbdOdhtb2CTw=](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQENWlYbt9dcj9vuc9DjBqDH-deRV2kYVxD2RLGIzQBnCNsw_XOEEYWNhc23ZJyYcFaqsuyiy4DUEp5xFcs_eO_GNANkqD1IGUqUtUziBVC4l0aCAGCsKk8MgNjJgukp2aMKe3hk0uWFkp5-pA2kaJ1dnouPZ7DKbdOdhtb2CTw=)
- [https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFwmn5owJFAO_qmcuh0qUOZjPFg4Mfx_cF6W6yD-RKYIwg0painDkHjFOEm6NDvHYAm71LWJob_NtFwk1xweplbZvMSWQPi11qPp-Aq3JKboZYbicIqN2KP709Zx7ZRKvc=](https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFwmn5owJFAO_qmcuh0qUOZjPFp4Mfx_cF6W6yD-RKYIwg0painDkHjFOEm6NDvHYAm71LWJob_NtFwk1xweplbZvMSWQPi11qPp-Aq3JKboZYbicIqN2KP709Zx7ZRKvc=)