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

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

このコミットは、Go言語の実験的な cookiejar パッケージに、IDNA (Internationalized Domain Names in Applications) および Punycode の toASCII 変換を実装するものです。これにより、クッキーが国際化ドメイン名(日本語や中国語などの非ASCII文字を含むドメイン名)を正しく処理できるようになります。具体的には、jar.go 内の canonicalHost 関数が、ホスト名を正規化する際に toASCII 変換を適用するように変更され、Punycodeのエンコード/デコードロジックを実装した punycode.go とそのテストファイル punycode_test.go が新規追加されています。

コミット

commit ffa0f8306020387ed7004b680f678473bf9fa65d
Author: Nigel Tao <nigeltao@golang.org>
Date:   Tue Feb 26 11:55:41 2013 +1100

    exp/cookiejar: implement IDNA/Punycode's toASCII.

    R=dr.volker.dobler
    CC=golang-dev
    https://golang.org/cl/7398049

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

https://github.com/golang/go/commit/ffa0f8306020387ed7004b680f678473bf9fa65d

元コミット内容

exp/cookiejar: implement IDNA/Punycode's toASCII.

R=dr.volker.dobler
CC=golang-dev
https://golang.org/cl/7398049

変更の背景

Webの国際化が進むにつれて、ドメイン名にASCII文字以外の文字(例: bücher.deü)を使用する国際化ドメイン名 (IDN) が普及しました。しかし、DNS (Domain Name System) は元々ASCII文字のみを扱うように設計されています。このギャップを埋めるために、IDNをASCII互換エンコーディング (ACE) に変換するメカニズムが必要となります。これがPunycodeであり、IDNAの主要な構成要素です。

HTTPクッキーは、特定のドメインに関連付けられて送受信されます。RFC 6265 (HTTP State Management Mechanism) は、クッキーのドメイン属性を処理する際に、ホスト名を「正規化されたホスト名」に変換する必要があると規定しています。この正規化プロセスには、IDNAの ToASCII 変換が含まれます。

このコミット以前の exp/cookiejar パッケージでは、この ToASCII 変換が実装されていませんでした。そのため、国際化ドメイン名を含むURLからクッキーを設定したり、国際化ドメイン名を持つサイトにクッキーを送信したりする際に、RFCの仕様に準拠せず、予期せぬ動作やセキュリティ上の問題が発生する可能性がありました。コミットメッセージの jar.go の変更箇所にあるコメントアウトされた TODO にも、「RFC 6265 の『正規化されたホスト名』は idna ToASCII 変換を必要とする」と明記されており、この機能の必要性が認識されていたことが伺えます。

このコミットは、cookiejar が国際化ドメイン名を正しく処理し、RFC 6265 に完全に準拠するための重要なステップです。

前提知識の解説

国際化ドメイン名 (IDN: Internationalized Domain Names)

IDNは、ASCII文字セットに含まれない文字(例: 日本語、中国語、アラビア語、キリル文字など)を含むドメイン名です。これにより、世界中のユーザーが自国語でドメイン名を登録・利用できるようになり、Webのアクセシビリティと使いやすさが向上します。

Punycode

Punycodeは、Unicode文字列をASCII文字のみで表現するためのエンコーディング方式です。IDNをDNSで扱えるようにするために開発されました。Punycodeでエンコードされたドメイン名は、通常 xn-- というプレフィックスで始まります。例えば、bücher.de は Punycode で xn--bcher-kva.de となります。

IDNA (Internationalized Domain Names in Applications)

IDNAは、アプリケーションがIDNを処理するための標準プロトコルです。IDNAは、IDNをPunycodeに変換する ToASCII 変換と、PunycodeをIDNに戻す ToUnicode 変換を定義しています。これにより、ユーザーはブラウザのアドレスバーに自国語のドメイン名を入力でき、内部的にはそれがPunycodeに変換されてDNSクエリが実行され、結果がユーザーには元のIDNで表示される、というシームレスな体験が実現されます。

RFC 6265 (HTTP State Management Mechanism)

HTTPクッキーの動作を定義する主要なRFCです。このRFCでは、クッキーのドメイン属性の処理において、ホスト名を「正規化されたホスト名」に変換する必要があることが明記されており、その変換にはIDNAの ToASCII 変換が含まれるとされています。

技術的詳細

このコミットは、主に以下の技術的側面を含んでいます。

  1. Punycodeエンコーディングアルゴリズムの実装: punycode.go ファイルは、RFC 3492で定義されているPunycodeエンコーディングアルゴリズムをGo言語で実装しています。このアルゴリズムは、Unicodeコードポイントの差分を効率的にASCII文字で表現するための複雑な数学的処理を含みます。

    • base, damp, initialBias, initialN, skew, tmax, tmin などの定数は、RFC 3492のセクション5で指定されたPunycodeのパラメータです。
    • encode 関数は、Punycodeのエンコーディングプロセスの中核をなします。これは、入力文字列をASCII部分と非ASCII部分に分け、非ASCII部分をPunycodeアルゴリズムに従ってエンコードします。
    • encodeDigit 関数は、Punycodeの数字をASCII文字に変換します。
    • adapt 関数は、Punycodeのバイアス適応関数であり、エンコーディング効率を最適化するために使用されます。
  2. IDNA toASCII 変換の実装: punycode.go の後半部分では、IDNAの toASCII 変換が実装されています。

    • acePrefix 定数 (xn--) は、ASCII互換エンコーディングのプレフィックスです。
    • toASCII 関数は、ドメイン名またはドメインラベルを受け取り、それが既にASCIIである場合はそのまま返し、そうでない場合はPunycodeエンコードを適用して xn-- プレフィックスを付加します。ドメイン名が複数のラベル(例: www.bücher.dewww, bücher, de)で構成されている場合、各ラベルに対して個別に toASCII 変換を適用し、最後にドットで結合します。
    • ascii 関数は、文字列が完全にASCII文字で構成されているかをチェックするヘルパー関数です。
  3. cookiejar パッケージへの統合: jar.go ファイルの canonicalHost 関数が変更され、ホスト名を正規化する際に新しく実装された toASCII 関数を使用するようになりました。これにより、cookiejar は国際化ドメイン名をRFC 6265の仕様に従って処理できるようになります。

  4. テストケースの追加: punycode_test.go ファイルには、PunycodeエンコーディングおよびIDNA toASCII 変換の正確性を検証するための広範なテストケースが追加されています。これらのテストケースには、RFC 3492のセクション7.1で提供されている公式のテストベクトルが含まれており、実装の信頼性を保証します。

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

src/pkg/exp/cookiejar/jar.go

--- a/src/pkg/exp/cookiejar/jar.go
+++ b/src/pkg/exp/cookiejar/jar.go
@@ -301,18 +301,11 @@ func canonicalHost(host string) (string, error) {
 			return "", err
 		}
 	}
-
 	if strings.HasSuffix(host, ".") {
 		// Strip trailing dot from fully qualified domain names.
 		host = host[:len(host)-1]
 	}
-
-	// TODO: the "canonicalized host name" of RFC 6265 requires the idna ToASCII
-	// transformation. Possible solutions:
-	//  - promote package idna from go.net to go and import "net/idna"
-	//  - document behavior as a BUG
-
-	return host, nil
+	return toASCII(host)
 }

 // hasPort returns whether host contains a port number. host may be a host
  • canonicalHost 関数が、ホスト名の末尾のドットを削除した後、toASCII(host) を呼び出すように変更されました。これにより、ホスト名がIDNAの ToASCII 変換を経て正規化されるようになります。以前の TODO コメントが解決されています。

src/pkg/exp/cookiejar/jar_test.go

--- a/src/pkg/exp/cookiejar/jar_test.go
+++ b/src/pkg/exp/cookiejar/jar_test.go
@@ -49,8 +49,8 @@ var canonicalHostTests = map[string]string{
 	"192.168.0.5:8080":        "192.168.0.5",
 	"2001:4860:0:2001::68":    "2001:4860:0:2001::68",
 	"[2001:4860:0:::68]:8080": "2001:4860:0:::68",
-\t// "www.bücher.de":        "www.xn--bcher-kva.de",  // TODO de-comment once proper idna is available
-\t"www.example.com.": "www.example.com",
+\t"www.bücher.de":           "www.xn--bcher-kva.de",
+\t"www.example.com.":        "www.example.com",
 }

 func TestCanonicalHost(t *testing.T) {
  • canonicalHostTests のテストケースで、"www.bücher.de" の期待値が "www.xn--bcher-kva.de" となるようにコメントアウトが解除され、IDNA変換が正しく行われることを検証するようになりました。

src/pkg/exp/cookiejar/punycode.go (新規ファイル)

PunycodeエンコーディングアルゴリズムとIDNA toASCII 変換の実装が含まれています。

src/pkg/exp/cookiejar/punycode_test.go (新規ファイル)

punycode.go で実装されたPunycodeエンコーディングおよびIDNA toASCII 変換のテストケースが含まれています。RFC 3492の公式テストベクトルが多数含まれています。

コアとなるコードの解説

このコミットの核心は、src/pkg/exp/cookiejar/punycode.go に新規追加された toASCII 関数と、それを呼び出すように変更された src/pkg/exp/cookiejar/jar.gocanonicalHost 関数です。

punycode.gotoASCII 関数は、国際化ドメイン名(例: bücher.de)を受け取り、それをDNSで扱えるASCII互換形式(例: xn--bcher-kva.de)に変換します。この変換は、ドメイン名をドットで区切られた各ラベルに分割し、各ラベルが非ASCII文字を含む場合にPunycodeエンコーディングを適用することで行われます。Punycodeエンコーディング自体は、RFC 3492に厳密に従って実装された encode 関数によって行われます。

jar.gocanonicalHost 関数は、HTTPクッキーのドメイン属性を処理する際に、ホスト名を正規化するために使用されます。この関数が toASCII を呼び出すようになったことで、cookiejar は国際化ドメイン名を含むクッキーをRFC 6265の仕様に準拠して正しく処理できるようになりました。これにより、Go言語の cookiejar は、より広範なWeb環境で適切に機能するようになります。

関連リンク

参考にした情報源リンク

  • 上記のRFCドキュメント
  • Go言語の公式ドキュメントおよびソースコード
  • Punycodeに関する一般的な技術解説記事