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

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

このコミットは、Go言語の標準ライブラリにHTTPクッキーを管理するための新しいパッケージ exp/cookiejar を導入するものです。このコミット自体はAPIの定義のみを含み、実際の機能実装は後続のコミットで行われる予定です。

コミット

commit 478aff3d4d7eea7f9980f960957eb21ae77aa2c2
Author: Nigel Tao <nigeltao@golang.org>
Date:   Tue Nov 27 18:20:44 2012 +1100

    exp/cookiejar: new package.
    
    This CL defines the API. Implementation will come in follow-up CLs.
    
    Update #1960.
    
    R=bradfitz, dr.volker.dobler, rsc
    CC=golang-dev
    https://golang.org/cl/6849092

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

https://github.com/golang/go/commit/478aff3d4d7eea7f9980f960957eb21ae77aa2c2

元コミット内容

exp/cookiejar: new package. This CL defines the API. Implementation will come in follow-up CLs. Update #1960.

変更の背景

このコミットは、Go言語の標準ライブラリにRFC 6265に準拠したHTTPクッキー管理機能を追加するための第一歩です。既存のnet/httpパッケージにはhttp.CookieJarインターフェースが存在しますが、その具体的な実装は提供されていませんでした。そのため、ユーザーは独自のクッキージャーを実装するか、サードパーティのライブラリを使用する必要がありました。

この変更の背景には、Go言語のIssue #1960があります。このIssueは、GoのHTTPクライアントがクッキーを適切に処理できるように、RFC 6265に準拠したクッキージャーの実装を求めるものでした。RFC 6265は、HTTP State Management Mechanism(HTTPステート管理メカニズム)を定義しており、WebブラウザやHTTPクライアントがどのようにクッキーを保存、送信、および管理すべきかを詳細に規定しています。

このコミットは、まずAPIを定義することで、将来的な実装の基盤を築くことを目的としています。これにより、GoのHTTPクライアントがより堅牢で標準に準拠したクッキー処理を行えるようになり、Webアプリケーションとの連携がスムーズになります。

前提知識の解説

HTTPクッキーは、WebサーバーがユーザーのWebブラウザに送信する小さなデータの一部です。ブラウザは、そのクッキーを保存し、同じサーバーへの後続のリクエストとともに送り返します。これにより、サーバーはユーザーの状態(ログイン情報、ショッピングカートの内容、ユーザー設定など)を記憶することができます。

RFC 6265: HTTP State Management Mechanism

RFC 6265は、HTTPクッキーの動作を定義する標準仕様です。これには、クッキーの属性(Expires, Max-Age, Domain, Path, Secure, HttpOnly, SameSiteなど)、クッキーの生成、保存、送信、削除のルールが含まれます。このRFCに準拠することで、異なるブラウザやクライアント間でのクッキーの互換性とセキュリティが保証されます。

http.CookieJar インターフェース (Go言語)

Go言語のnet/httpパッケージには、CookieJarというインターフェースが定義されています。これは、HTTPクライアントがクッキーを保存および取得するためのメカニズムを提供します。

type CookieJar interface {
    SetCookies(u *url.URL, cookies []*Cookie)
    Cookies(u *url.URL) []*Cookie
}
  • SetCookies(u *url.URL, cookies []*Cookie): 指定されたURLに対して、サーバーから受信したクッキーを保存します。
  • Cookies(u *url.URL) []*Cookie: 指定されたURLに対して送信すべきクッキーを返します。

このインターフェースを実装することで、HTTPクライアントは自動的にクッキーを管理できるようになります。

Public Suffix List (公開サフィックスリスト)

公開サフィックスリストは、ドメイン名の「公開サフィックス」を定義するリストです。例えば、example.comの公開サフィックスはcomfoo.co.ukの公開サフィックスはco.ukです。このリストは、セキュリティ上の理由から非常に重要です。クッキーは、そのドメインの公開サフィックスよりも上位のドメインに対して設定されるべきではありません。例えば、example.comcomに対してクッキーを設定することはできません。これは、悪意のあるサイトが他のサイトのクッキーを盗むことを防ぐためです。

技術的詳細

このコミットでは、exp/cookiejarパッケージ内に以下の主要なインターフェースと構造体が定義されています。

  1. PublicSuffixList インターフェース:

    • PublicSuffix(domain string) string: 与えられたドメインの公開サフィックスを返します。
    • String() string: この公開サフィックスリストのソースに関する説明(タイムスタンプやバージョン番号など)を返します。これは、クッキージャーがリストの変更を検出し、必要に応じてクッキーを更新するために使用されます。
    • このインターフェースは、クッキーのセキュリティとプライバシーを確保するために不可欠です。クッキーが設定されるドメインが、その公開サフィックスを超えていないことを保証するために使用されます。
  2. Storage インターフェース:

    • Lock() / Unlock(): ストレージへの並行アクセスを制御するためのロックメカニズムを提供します。
    • Add(key string, entries ...Entry) error: 指定されたキーにエントリを追加します。既存のエントリがある場合は更新されます。
    • Delete(key string) error: 指定されたキーに関連する全てのエントリを削除します。
    • Entries(key string, f func(entry Entry) (Action, time.Time, error)) error: 指定されたキーのエントリをイテレートし、各エントリに対して関数fを呼び出します。fは、エントリの更新(Update)または削除(Delete)を指示できます。
    • Keys(f func(key string) error) error: ストレージ内の全てのキーをイテレートし、各キーに対して関数fを呼び出します。
    • Entry 構造体: Subkey, Data, Creation, LastAccess を含む、ストレージ内の単一のエントリを表します。
    • Action 型: Pass, Update, Delete の3つの定数を持つ列挙型で、Entriesメソッドのコールバック関数が返すアクションを定義します。
    • ValidStorageKey(key string) bool: ストレージキーが有効な形式であるかを検証するヘルパー関数です。キーは小文字の英数字、ハイフン、ドットのみを含み、少なくとも1つの非ドット文字を持つ必要があります。
  3. Options 構造体:

    • Storage Storage: クッキージャーが使用するストレージ実装を指定します。nilであってはなりません。
    • PublicSuffixList PublicSuffixList: クッキージャーが使用する公開サフィックスリスト実装を指定します。nilであってはなりません。
  4. Jar 構造体:

    • storage Storage: 内部で使用するStorageインターフェースの実装。
    • psList PublicSuffixList: 内部で使用するPublicSuffixListインターフェースの実装。
    • New(o *Options) *Jar: 新しいJarインスタンスを作成するコンストラクタ関数。
  5. Jar 構造体のメソッド (未実装):

    • Cookies(u *url.URL) []*http.Cookie: http.CookieJarインターフェースのCookiesメソッドの実装(TODOコメントあり)。
    • SetCookies(u *url.URL, cookies []*http.Cookie): http.CookieJarインターフェースのSetCookiesメソッドの実装(TODOコメントあり)。

このコミットでは、これらのインターフェースと構造体の定義に焦点を当てており、実際のクッキーの保存・取得ロジックはまだ実装されていません。これは、API設計を先行させ、その後の実装を段階的に進めるという開発アプローチを示しています。

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

このコミットで追加されたファイルは以下の3つです。

  1. src/pkg/exp/cookiejar/jar.go:

    • PublicSuffixList インターフェースの定義。
    • Options 構造体の定義。
    • Jar 構造体の定義。
    • New コンストラクタ関数の定義。
    • Jar.Cookies および Jar.SetCookies メソッドのシグネチャ定義(実装はTODO)。
  2. src/pkg/exp/cookiejar/storage.go:

    • Storage インターフェースの定義。
    • Entry 構造体の定義。
    • Action 型と関連する定数(Pass, Update, Delete)の定義。
    • ValidStorageKey ヘルパー関数の定義。
  3. src/pkg/exp/cookiejar/storage_test.go:

    • ValidStorageKey 関数のテストケースを定義する validStorageKeyTests マップ。
    • TestValidStorageKey テスト関数。

コアとなるコードの解説

jar.go

jar.goでは、http.CookieJarインターフェースを実装するための主要な構造体Jarと、その依存関係であるPublicSuffixListインターフェースが定義されています。

PublicSuffixListインターフェースは、ドメインの公開サフィックスを特定するための抽象化を提供します。これにより、クッキージャーは、悪意のあるクッキー設定を防ぐために、ドメインのセキュリティ境界を尊重することができます。String()メソッドは、リストのバージョン管理を可能にし、リストが更新された場合にクッキーを再評価するメカニズムを提供します。

Options構造体は、Jarを初期化する際に必要な設定(StoragePublicSuffixListの実装)をカプセル化します。これにより、Jarの作成が柔軟になります。

Jar構造体は、http.CookieJarインターフェースの具体的な実装となることを意図しており、内部にStoragePublicSuffixListのインスタンスを保持します。New関数は、これらの依存関係を注入してJarのインスタンスを生成します。

CookiesSetCookiesメソッドは、http.CookieJarインターフェースの要件を満たすために定義されていますが、このコミット時点ではまだ実装されていません。これは、API設計と実装を分離する一般的なソフトウェア開発プラクティスに従っています。

storage.go

storage.goでは、クッキーデータを永続化または一時的に保存するための抽象化であるStorageインターフェースが定義されています。このインターフェースは、クッキーの追加、削除、およびイテレーションのためのメソッドを提供します。

Storageインターフェースは、Lock()Unlock()メソッドを通じて、並行アクセスに対する安全性を考慮しています。これは、複数のゴルーチンが同時にクッキージャーにアクセスする可能性があるため、データの一貫性を保つ上で重要です。

Addメソッドは、新しいクッキーエントリをストレージに追加します。既存のエントリと同じキーとサブキーを持つ場合は、古いエントリが新しいエントリに置き換えられます。これは、クッキーの更新動作を反映しています。

Deleteメソッドは、特定のキーに関連するすべてのクッキーエントリを削除します。

Entriesメソッドは、特定のキーに関連するクッキーエントリをイテレートするための強力なメカニズムを提供します。コールバック関数fを使用することで、イテレーション中に各エントリに対してカスタムロジック(例えば、有効期限のチェックやアクセス時間の更新)を適用できます。Action型は、このコールバック関数がストレージに対してどのような操作を行うべきかを指示するために使用されます。

Keysメソッドは、ストレージ内のすべてのキーをイテレートするために使用されます。

ValidStorageKey関数は、ストレージキーの形式を検証するためのユーティリティです。これは、ストレージ実装が期待するキーの形式を強制し、潜在的な問題を防止するのに役立ちます。

storage_test.go

storage_test.goは、ValidStorageKey関数の基本的な単体テストを提供します。このテストは、有効なキーと無効なキーの様々な組み合わせを検証し、関数が期待通りに動作することを確認します。これは、新しい機能が追加される際に、その動作が正しく、将来の変更によって壊れないことを保証するための良いプラクティスです。

関連リンク

参考にした情報源リンク