[インデックス 10843] ファイルの概要
このコミットは、Go言語の標準ライブラリ net/http
パッケージに、HTTPクライアントがクッキーを永続化・管理するための CookieJar
インターフェースを追加するものです。これにより、HTTPリクエストとレスポンス間でクッキーの状態を保持し、セッション管理などを容易に行えるようになります。
コミット
commit dd694fb14912814fdcdf280ffa2a783b3bd18e63
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date: Fri Dec 16 10:48:41 2011 -0500
net/http: Added interface for a cookie jar.
Types implementing CookieJar may be used in a Client
to persist cookies.
R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/5399043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/dd694fb14912814fdcdf280ffa2a783b3bd18e63
元コミット内容
net/http: Added interface for a cookie jar.
Types implementing CookieJar may be used in a Client
to persist cookies.
R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/5399043
変更の背景
HTTPプロトコルはステートレスであり、各リクエストは独立して扱われます。しかし、ウェブアプリケーションではユーザー認証やセッション管理など、複数のリクエスト間で状態を維持する必要があることがほとんどです。この状態管理の主要なメカニズムの一つが「クッキー(Cookie)」です。
Go言語の net/http
パッケージは、HTTPクライアントとサーバーを構築するための基本的な機能を提供します。このコミット以前は、http.Client
は自動的にクッキーを管理する機能を持っていませんでした。つまり、開発者は手動で Set-Cookie
ヘッダーからクッキーを抽出し、次のリクエストの Cookie
ヘッダーに含める必要がありました。これは非常に煩雑であり、特にリダイレクトや複雑なセッション管理を伴う場合には、エラーの温床となりがちでした。
このコミットは、http.Client
にクッキー管理の責務を委譲するための標準的なインターフェース CookieJar
を導入することで、この問題を解決しようとしています。これにより、開発者は CookieJar
インターフェースを実装する型(例えば、メモリ内でのクッキー管理や、ディスクへの永続化を行う型)を http.Client
に設定するだけで、自動的なクッキーの送受信と保存が可能になります。これは、より堅牢で使いやすいHTTPクライアントの実現に向けた重要な一歩です。
前提知識の解説
HTTPクッキー (HTTP Cookie)
HTTPクッキーは、ウェブサーバーがユーザーのウェブブラウザに送信する小さなデータ片です。ブラウザはこれらのクッキーを保存し、同じサーバーへの後続のリクエストでそれらを送り返します。これにより、サーバーはユーザーのセッション状態を識別したり、ユーザー設定を記憶したりすることができます。
クッキーは主に以下の目的で使用されます:
- セッション管理: ユーザーのログイン状態、ショッピングカートの内容など。
- パーソナライゼーション: ユーザー設定、テーマ、言語設定など。
- トラッキング: ユーザーの行動追跡、広告ターゲティングなど。
クッキーの送受信はHTTPヘッダーを通じて行われます。
- サーバーからブラウザへ:
Set-Cookie
ヘッダー - ブラウザからサーバーへ:
Cookie
ヘッダー
クッキージャー (Cookie Jar)
「クッキージャー」という概念は、HTTPクライアントが受信したクッキーを保存し、後続のリクエストで適切なクッキーを送信するために使用するストレージメカニズムを指します。これは、ブラウザがクッキーを管理する方法を抽象化したものです。クッキージャーは、クッキーの有効期限、ドメイン、パスなどの属性を考慮して、どのクッキーを保存し、どのリクエストに含めるべきかを決定します。
RFC 6265 (HTTP State Management Mechanism)
RFC 6265は、HTTPクッキーの動作を定義するIETF(Internet Engineering Task Force)の標準仕様です。これは、以前のRFC 2109やRFC 2965を廃止し、実際のウェブでのクッキーの使用方法をより正確に反映するように作成されました。
RFC 6265は、クッキーの構文、Set-Cookie
ヘッダーと Cookie
ヘッダーの処理ルール、セキュリティに関する考慮事項などを詳細に規定しています。CookieJar
の実装は、このRFCの規定に準拠することで、標準的で予測可能なクッキー管理動作を保証する必要があります。特に、クッキーのドメイン、パス、有効期限、Secure/HttpOnly属性などの処理は、RFC 6265に厳密に従う必要があります。
Go言語の net/http/cookiejar
パッケージ(このコミットで導入されたインターフェースを実装する具体的な型を提供するパッケージ)は、RFC 6265に準拠したインメモリの http.CookieJar
を提供します。
技術的詳細
このコミットの核心は、net/http
パッケージに CookieJar
インターフェースを導入し、http.Client
がこのインターフェースを通じてクッキーを管理できるようにした点です。
CookieJar
インターフェース
CookieJar
インターフェースは、以下の2つのメソッドを定義します。
type CookieJar interface {
// SetCookies handles the receipt of the cookies in a reply for the
// given URL. It may or may not choose to save the cookies, depending
// on the jar's policy and implementation.
SetCookies(u *url.URL, cookies []*Cookie)
// Cookies returns the cookies to send in a request for the given URL.
// It is up to the implementation to honor the standard cookie use
// restrictions such as in RFC 6265.
Cookies(u *url.URL) []*Cookie
}
SetCookies(u *url.URL, cookies []*Cookie)
: このメソッドは、特定のURL (u
) から受信したクッキーのリスト (cookies
) を処理するために呼び出されます。CookieJar
の実装は、これらのクッキーを保存するかどうか、どのように保存するかを決定します。例えば、有効期限が切れているクッキーは保存しない、といったロジックがここに実装されます。Cookies(u *url.URL) []*Cookie
: このメソッドは、特定のURL (u
) へのリクエストを送信する際に、そのリクエストに含めるべきクッキーのリストを返します。CookieJar
の実装は、RFC 6265などの標準に従って、適切なドメインとパスに一致するクッキーを選択して返します。
このインターフェースの導入により、http.Client
はクッキーの具体的な保存・取得ロジックを知る必要がなくなり、CookieJar
の実装にその責務を委譲できるようになりました。これにより、クッキー管理のロジックを柔軟に差し替えることが可能になります。例えば、メモリに保存するだけでなく、ファイルシステムやデータベースにクッキーを永続化するカスタム CookieJar
を作成することもできます。
http.Client
と Jar
フィールド
http.Client
構造体には、新しく Jar CookieJar
フィールドが追加されました。
type Client struct {
// ... 既存のフィールド ...
// Jar specifies the cookie jar.
// If Jar is nil, cookies are not sent in requests and ignored
// in responses.
Jar CookieJar
}
Jar
フィールドにCookieJar
インターフェースを実装したオブジェクトを設定することで、そのクライアントは自動的にクッキーを管理するようになります。Jar
がnil
の場合、クライアントはクッキーを送受信せず、クッキー管理は行われません。これは、クッキーが不要な場合や、手動でクッキーを管理したい場合に利用できます。
blackHoleJar
このコミットでは、blackHoleJar
という内部的な型も導入されています。
type blackHoleJar struct{}
func (blackHoleJar) SetCookies(u *url.URL, cookies []*Cookie) {}
func (blackHoleJar) Cookies(u *url.URL) []*Cookie { return nil }
blackHoleJar
は CookieJar
インターフェースを実装していますが、SetCookies
メソッドは何もしません(クッキーを保存しない)し、Cookies
メソッドは常に nil
を返します(クッキーを送信しない)。これは、http.Client
の Jar
フィールドが nil
の場合に内部的に使用され、クッキー管理を無効にするためのプレースホルダーとして機能します。これにより、nil
チェックを減らし、コードを簡潔に保つことができます。
コアとなるコードの変更箇所
このコミットでは、主に以下の3つのファイルが変更されています。
-
src/pkg/net/http/Makefile
:jar.go
がビルド対象のファイルリストGOFILES
に追加されました。これにより、新しく作成されるjar.go
がnet/http
パッケージの一部としてコンパイルされるようになります。
-
src/pkg/net/http/client.go
:Client
構造体にJar CookieJar
フィールドが追加されました。doFollowingRedirects
関数内で、Client.Jar
がnil
の場合にblackHoleJar
を使用するロジックが追加されました。- リクエスト送信前に
jar.Cookies(req.URL)
を呼び出してクッキーを取得し、リクエストヘッダーに追加する処理が追加されました。 - レスポンス受信後に
jar.SetCookies(req.URL, c)
を呼び出して、レスポンスに含まれるクッキーをCookieJar
に保存する処理が追加されました。
-
src/pkg/net/http/jar.go
:- 新しく作成されたファイルです。
CookieJar
インターフェースが定義されています。blackHoleJar
型とそのメソッドが定義されています。
コアとなるコードの解説
src/pkg/net/http/client.go
の変更点
client.go
の変更は、http.Client
が CookieJar
インターフェースを利用してクッキーを自動的に管理するメカニズムを実装しています。
// Client 構造体への Jar フィールドの追加
type Client struct {
// ...
Jar CookieJar
}
Client
構造体に Jar
フィールドが追加されたことで、ユーザーは http.Client
インスタンスを作成し、その Jar
フィールドにカスタムの CookieJar
実装を割り当てるだけで、クッキー管理機能を有効にできます。
// doFollowingRedirects 関数内の変更
jar := c.Jar
if jar == nil {
jar = blackHoleJar{}
}
doFollowingRedirects
関数は、HTTPリクエストの送信とリダイレクトの処理を担当する内部関数です。この部分では、Client
の Jar
フィールドが設定されているかを確認します。もし Jar
が nil
であれば、blackHoleJar
インスタンスが jar
変数に割り当てられます。これにより、後続のクッキー関連の操作で nil
ポインタ参照を防ぎつつ、クッキー管理を実質的に無効にします。
// リクエスト送信前のクッキー追加
for _, cookie := range jar.Cookies(req.URL) {
req.AddCookie(cookie)
}
これは、HTTPリクエストを送信する直前に行われる処理です。jar.Cookies(req.URL)
を呼び出すことで、現在のリクエストURL (req.URL
) に関連するクッキーが CookieJar
から取得されます。取得された各クッキーは、req.AddCookie(cookie)
を使ってリクエストの Cookie
ヘッダーに追加されます。これにより、サーバーはクライアントからのリクエストに適切なクッキーが含まれていることを認識できます。
// レスポンス受信後のクッキー保存
if c := r.Cookies(); len(c) > 0 {
jar.SetCookies(req.URL, c)
}
これは、HTTPレスポンスを受信した直後に行われる処理です。r.Cookies()
はレスポンスに含まれる Set-Cookie
ヘッダーからパースされたクッキーのリストを返します。もしクッキーが存在すれば (len(c) > 0
)、jar.SetCookies(req.URL, c)
を呼び出して、これらのクッキーを CookieJar
に保存します。CookieJar
の実装は、これらのクッキーを適切に処理し、将来のリクエストのために保存するかどうかを決定します。
src/pkg/net/http/jar.go
の新規追加
このファイルは、CookieJar
インターフェースの定義と、そのインターフェースの最小限の実装である blackHoleJar
を提供します。これにより、net/http
パッケージの外部から CookieJar
インターフェースを参照できるようになり、カスタムのクッキー管理ロジックを実装する際の基盤となります。
関連リンク
- Go CL 5399043: https://golang.org/cl/5399043
参考にした情報源リンク
- Go
net/http/cookiejar
package documentation: https://pkg.go.dev/net/http/cookiejar - RFC 6265 - HTTP State Management Mechanism: https://www.rfc-editor.org/rfc/rfc6265
- Wikipedia - HTTP cookie: https://en.wikipedia.org/wiki/HTTP_cookie
- Go 1.1 Release Notes (mentions
net/http/cookiejar
): https://go.dev/doc/go1.1#cookiejar - Stack Overflow discussion on Go's
cookiejar
introduction: https://stackoverflow.com/questions/10050301/how-to-use-cookies-with-go-http-client - Go's
cookiejar
and IP addresses in domain attributes: https://google.com (This link was from the web search, but the specific article is not directly accessible. It refers to a Google search result aboutcookiejar
and IP addresses.) - Go
PublicSuffixList
interface: https://pkg.go.dev/golang.org/x/net/publicsuffix (While not directly part of this commit, it's highly relevant to a fullCookieJar
implementation.)