[インデックス 18171] ファイルの概要
このコミットは、Go言語の標準ライブラリである net/http パッケージ内のクッキー処理に関するものです。具体的には、クッキーの Domain および Path フィールドのパースに関するTODOコメントが削除されています。これは、これらのフィールドがGo 1.0以降、未処理のワイヤーデータとして扱われてきた現状を維持し、その挙動が多くのアプリケーションにとって問題ないという判断に基づいています。
コミット
commit 939b3fa39eafff3f10c092ef882c935c0bce9c06
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date: Mon Jan 6 10:00:58 2014 -0800
net/http: remove todos from cookie code
The Domain and Path field of a parsed cookie have been
the unprocessed wire data since Go 1.0; this seems to
be okay for most applications so let's keep it.
Returning the unprocessed wire data makes it easy to
handle nonstandard or even broken clients without
consulting Raw or Unparsed of a cookie.
The RFC 6265 parsing rules for domain and path are
currently buried in net/http/cookiejar but could be
exposed in net/http if necessary.
R=bradfitz, nigeltao
CC=golang-codereviews
https://golang.org/cl/48060043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/939b3fa39eafff3f10c092ef882c935c0bce9c06
元コミット内容
net/http: クッキーコードからTODOを削除
パースされたクッキーの Domain および Path フィールドは、Go 1.0以降、未処理のワイヤーデータとして扱われてきました。これはほとんどのアプリケーションで問題ないように思われるため、このまま維持することにします。
未処理のワイヤーデータを返すことで、クッキーの Raw や Unparsed を参照することなく、非標準的または破損したクライアントを簡単に処理できます。
Domain および Path のRFC 6265パースルールは現在 net/http/cookiejar に隠されていますが、必要であれば net/http で公開することも可能です。
変更の背景
このコミットの背景には、Go言語の net/http パッケージにおけるクッキーの Domain および Path フィールドの扱いに関する設計上の決定があります。
元々、src/pkg/net/http/cookie.go のコードには、Domain と Path のパース処理を追加するためのTODOコメントが存在していました。これは、HTTPクッキーの仕様を定義するRFC 6265に厳密に従ったパースロジックを将来的に実装する意図があったことを示唆しています。
しかし、Go 1.0のリリース以降、これらのフィールドはHTTPレスポンスヘッダーから受け取ったそのままの文字列(「未処理のワイヤーデータ」)として Cookie 構造体に格納されてきました。この挙動は、多くのWebアプリケーションやクライアントにとって特に問題を引き起こすことなく機能していました。
コミットの著者は、この既存の挙動を維持することに利点があると考えました。その主な理由は以下の通りです。
- 後方互換性: Go 1.0以降の既存のコードベースがこの挙動に依存しているため、変更は破壊的となる可能性があります。
- 柔軟性: 未処理のデータをそのまま保持することで、RFCに厳密に従わない、あるいは意図的に非標準的な形式でクッキーを送信するクライアント(例えば、古いブラウザや特定のシステム)からのデータも、開発者が柔軟に処理できるようになります。
Cookie構造体のRawやUnparsedフィールドを別途参照する必要がなくなるため、コードが簡潔になります。 - 実用性: 厳密なRFC 6265のパースルールは、Goの
net/http/cookiejarパッケージ(クッキーの保存と管理を行うクライアントサイドのクッキー実装)には既に実装されています。これは、クライアントがクッキーを送信する際に、ブラウザのように厳密なルールに従ってクッキーを生成・管理する必要があるためです。しかし、サーバーサイドで受信したクッキーをパースするnet/httpパッケージにおいては、必ずしもそこまで厳密なパースが必要ではないという判断がなされました。サーバーは、クライアントが送信してきたデータをそのまま受け取り、必要に応じてアプリケーション層で解釈する方が、より堅牢であるという考え方です。
これらの理由から、Domain と Path のパースに関するTODOコメントは削除され、未処理のワイヤーデータをそのまま保持する現在の実装が正式なものとして承認されました。これにより、net/http パッケージは、クッキーの受信と基本的な構造化に焦点を当て、より複雑なRFC準拠のパースは net/http/cookiejar のような上位レイヤーのパッケージに任せるという役割分担が明確になりました。
前提知識の解説
このコミットを理解するためには、以下の前提知識が役立ちます。
1. HTTPクッキー (HTTP Cookies)
HTTPクッキーは、WebサーバーがユーザーのWebブラウザに送信する小さなデータ片です。ブラウザはこれらのクッキーを保存し、同じサーバーへの後続のリクエストでそれらを送り返します。これにより、サーバーはユーザーの状態を記憶したり、ユーザーを識別したりすることができます。
クッキーは主に Set-Cookie HTTPレスポンスヘッダーによってサーバーからクライアントに設定され、Cookie HTTPリクエストヘッダーによってクライアントからサーバーに送信されます。
クッキーにはいくつかの属性があります。このコミットで特に重要なのは Domain と Path です。
Domain属性: クッキーが送信されるドメインを指定します。例えば、Domain=example.comと設定されたクッキーは、example.comおよびそのサブドメイン(www.example.comなど)に送信されます。この属性が設定されていない場合、クッキーを設定したサーバーのホスト名がデフォルトのドメインとなります。Path属性: クッキーが送信されるURLパスを指定します。例えば、Path=/docsと設定されたクッキーは、/docsおよびそのサブパス(/docs/faqなど)に送信されます。この属性が設定されていない場合、クッキーを設定したリクエストのパスがデフォルトのパスとなります。
2. RFC 6265 (HTTP State Management Mechanism)
RFC 6265は、HTTPクッキーの動作と構文を定義するインターネット標準ドキュメントです。これは、以前のRFC 2965やRFC 2109を置き換えるもので、クッキーのパース、保存、送信に関する詳細なルールを規定しています。
特に、Domain と Path 属性のパースルールは複雑で、例えば Domain 属性の値がドットで始まるかどうか、IPアドレスであるかどうか、あるいはホスト名と一致するかどうかなど、様々な条件が考慮されます。これらのルールは、セキュリティ上の理由(例えば、あるドメインのクッキーが別のドメインに誤って送信されるのを防ぐ)や、クッキーの意図しない共有を防ぐために重要です。
3. Go言語の net/http パッケージ
net/http パッケージは、Go言語でHTTPクライアントとサーバーを実装するための基本的な機能を提供します。このパッケージには、HTTPリクエストとレスポンスのパース、ヘッダーの処理、クッキーの読み書きなどの機能が含まれています。
http.Cookie構造体: クッキーの各属性(Name,Value,Domain,Path,Expiresなど)を保持する構造体です。http.Request.Cookie()/http.Request.Cookies(): 受信したHTTPリクエストからクッキーを読み取るためのメソッドです。http.SetCookie(): HTTPレスポンスにクッキーを設定するための関数です。
4. Go言語の net/http/cookiejar パッケージ
net/http/cookiejar パッケージは、HTTPクライアントがクッキーを保存し、管理するための「クッキージャー」の実装を提供します。これは、Webブラウザがクッキーを扱う方法を模倣しており、RFC 6265に厳密に従ってクッキーの保存、有効期限、ドメインとパスのマッチング、セキュリティポリシーなどを処理します。
このパッケージは、特にHTTPクライアントが複数のリクエスト間で状態を維持する必要がある場合に有用です。net/http パッケージがHTTPプロトコルの低レベルな側面を扱うのに対し、net/http/cookiejar はより高レベルなクッキー管理ロジックを提供します。
このコミットの文脈では、net/http がサーバーサイドで受信したクッキーの「生データ」を扱うのに対し、net/http/cookiejar はクライアントサイドでクッキーを「厳密にパースし、管理する」という役割分担が重要になります。
技術的詳細
このコミットの技術的な核心は、Goの net/http パッケージがHTTPクッキーの Domain および Path フィールドをどのように扱うか、という点にあります。
既存の挙動(Go 1.0以降)
コミットメッセージが述べているように、Go 1.0以降、net/http パッケージは受信したクッキーの Domain および Path フィールドを、HTTPヘッダーから読み取った「未処理のワイヤーデータ」(raw wire data)として http.Cookie 構造体に格納していました。これは、RFC 6265で定義されているような厳密なパースルール(例えば、ドメイン名の正規化、パスの正規化、不正な値の拒否など)を適用せずに、文字列をそのまま保持するという意味です。
例えば、Set-Cookie: name=value; Domain=.example.com; Path=/foo/bar というヘッダーを受け取った場合、http.Cookie.Domain には ".example.com" が、http.Cookie.Path には "/foo/bar" がそのまま格納されます。RFC 6265では、ドメインがドットで始まる場合(.example.com)は、先頭のドットを削除して example.com として扱うなどの正規化ルールが存在しますが、net/http はこれを適用していませんでした。
TODOコメントの存在とその意味
削除されたTODOコメント(// TODO: Add domain parsing と // TODO: Add path parsing)は、将来的にRFC 6265に準拠した厳密なパースロジックを net/http パッケージに追加する意図があったことを示しています。これは、より堅牢で標準に準拠したクッキー処理を目指す開発者の一般的な考え方と一致します。
TODOコメント削除の理由と影響
このコミットは、これらのTODOコメントを削除することで、未処理のワイヤーデータをそのまま保持する既存の挙動を「意図された設計」として確定させました。その理由は、コミットメッセージに明記されています。
-
実用性と柔軟性:
- 「未処理のワイヤーデータを返すことで、クッキーの
RawやUnparsedを参照することなく、非標準的または破損したクライアントを簡単に処理できます。」 - これは、サーバーが様々なクライアント(古いブラウザ、非標準的な実装、あるいはバグのあるクライアント)からのクッキーを受け入れる際に、より寛容であることを意味します。厳密なパースルールを適用すると、わずかなフォーマットのずれでもクッキーが拒否されたり、誤ってパースされたりする可能性があります。未処理のデータをそのまま渡すことで、アプリケーション開発者は、必要に応じて独自のパースロジックを実装したり、特定の非標準的なケースをハンドリングしたりする柔軟性を得られます。
http.Cookie構造体にはRawフィールド(クッキーの生文字列)やUnparsedフィールド(パースできなかった属性のリスト)も存在しますが、DomainやPathが未処理のワイヤーデータとして直接利用できることで、これらのフィールドを別途参照して再パースする手間が省けます。
- 「未処理のワイヤーデータを返すことで、クッキーの
-
役割分担の明確化:
- 「RFC 6265パースルールは現在
net/http/cookiejarに隠されていますが、必要であればnet/httpで公開することも可能です。」 - これは、RFC 6265に厳密に準拠したクッキーのパースと管理は、主にクライアントサイドのクッキー管理を行う
net/http/cookiejarパッケージの役割であるという設計思想を示唆しています。 net/httpパッケージ(特にサーバーサイドの受信処理)は、HTTPプロトコルの基本的な構文解析とデータ構造へのマッピングに焦点を当て、より複雑なセマンティックな解釈や検証は、より高レベルのパッケージやアプリケーションロジックに委ねるというアプローチです。これにより、net/httpパッケージのコードベースはよりシンプルに保たれ、パフォーマンスも最適化されます。
- 「RFC 6265パースルールは現在
結論
このコミットは、net/http パッケージがクッキーの Domain および Path フィールドを「未処理のワイヤーデータ」として扱うという既存の挙動を、意図的な設計上の選択として確定させました。これは、実用性、柔軟性、そしてGo標準ライブラリ内でのパッケージ間の役割分担を考慮した結果です。開発者は、net/http が提供するクッキーデータがRFC 6265に厳密に準拠したパース済みデータではないことを理解し、必要に応じてアプリケーション層で追加の検証や正規化を行う必要があります。
コアとなるコードの変更箇所
変更は src/pkg/net/http/cookie.go ファイルの2箇所です。
--- a/src/pkg/net/http/cookie.go
+++ b/src/pkg/net/http/cookie.go
@@ -94,7 +94,6 @@ func readSetCookies(h Header) []*Cookie {
case "domain":
c.Domain = val
- // TODO: Add domain parsing
continue
case "max-age":
secs, err := strconv.Atoi(val)
@@ -121,7 +120,6 @@ func readSetCookies(h Header) []*Cookie {
case "path":
c.Path = val
- // TODO: Add path parsing
continue
}\
c.Unparsed = append(c.Unparsed, parts[i])
コアとなるコードの解説
このコミットで削除されたのは、src/pkg/net/http/cookie.go 内の readSetCookies 関数における2つのTODOコメントです。
readSetCookies 関数は、HTTPレスポンスヘッダーから Set-Cookie ヘッダーを読み取り、それを http.Cookie 構造体のスライスにパースする役割を担っています。この関数内で、クッキーの各属性(name=value, expires, domain, path など)がループ処理され、対応する http.Cookie 構造体のフィールドに値が割り当てられます。
削除されたTODOコメントは以下の行にありました。
-
case "domain":の下:c.Domain = val // TODO: Add domain parsing continueこの箇所は、
Set-CookieヘッダーからDomain属性の値 (val) を抽出し、それをc.Domainフィールドに直接割り当てています。削除されたTODOコメントは、ここにRFC 6265に準拠したドメインパースロジック(例えば、先頭のドットの削除や、不正なドメイン名の検証など)を追加する予定があったことを示していました。 -
case "path":の下:c.Path = val // TODO: Add path parsing continue同様に、この箇所は
Path属性の値 (val) を抽出し、c.Pathフィールドに直接割り当てています。削除されたTODOコメントは、ここにRFC 6265に準拠したパスパースロジック(例えば、パスの正規化や、不正なパスの検証など)を追加する予定があったことを示していました。
これらのTODOコメントが削除されたことで、net/http パッケージは、Domain と Path の値をHTTPヘッダーから受け取ったそのままの文字列として http.Cookie 構造体に格納し続けることが、正式な設計上の決定となりました。これは、前述の「変更の背景」と「技術的詳細」で説明したように、実用性、柔軟性、およびパッケージ間の役割分担を重視した結果です。
したがって、このコミットはコードの動作を変更するものではなく、将来の機能追加の計画(TODO)を削除し、既存の動作を「意図されたもの」として明確にするためのものです。
関連リンク
- Go言語の公式ドキュメント: https://golang.org/
- Go言語の
net/httpパッケージドキュメント: https://pkg.go.dev/net/http - Go言語の
net/http/cookiejarパッケージドキュメント: https://pkg.go.dev/net/http/cookiejar - このコミットのGoレビューシステム上のリンク: https://golang.org/cl/48060043
参考にした情報源リンク
- RFC 6265 - HTTP State Management Mechanism: https://datatracker.ietf.org/doc/html/rfc6265
- MDN Web Docs - HTTP cookies: https://developer.mozilla.org/ja/docs/Web/HTTP/Cookies
- Go言語のソースコード (特に
src/pkg/net/http/cookie.goとsrc/pkg/net/http/cookiejar/jar.go): https://github.com/golang/go - Go言語のコミット履歴とレビューシステム (Gerrit): https://go.googlesource.com/go/+log
- Go言語のIssue Tracker: https://github.com/golang/go/issues
- Go言語のメーリングリスト (golang-nuts, golang-dev, golang-codereviews): https://groups.google.com/g/golang-nuts など
- Go言語のブログや技術記事(一般的なGoのクッキー処理やHTTPに関する解説)I have generated the detailed technical explanation in Markdown format, following all the specified instructions and chapter structure. The output is provided directly to standard output as requested.