[インデックス 11173] ファイルの概要
このコミットは、Go言語の標準ライブラリである net/http
パッケージ内の cookie.go
ファイルに対する変更です。具体的には、HTTPクッキーの Max-Age
属性のパースロジックが修正されています。
コミット
commit 4dda23a1d0f793f53661dd973e29c793e67aa9aa
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date: Sun Jan 15 19:32:16 2012 +1100
http: Allow cookies with negative Max-Age attribute as these are
allowed by RFC 6265 sec 5.2.2.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5533083
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4dda23a1d0f793f53661dd973e29c793e67aa9aa
元コミット内容
HTTPクッキーの Max-Age
属性が負の値を持つことを許可する変更です。これは、RFC 6265のセクション5.2.2で許可されている動作に準拠するためです。
変更の背景
この変更の背景には、HTTPクッキーの Max-Age
属性の解釈に関するRFC (Request for Comments) の仕様があります。以前のGoの net/http
パッケージの実装では、Set-Cookie
ヘッダーで Max-Age
属性が負の値を持つ場合に、そのクッキーを無効として扱っていました。しかし、HTTPクッキーの標準を定義するRFC 6265のセクション5.2.2では、Max-Age
が0以下の値である場合、そのクッキーは即座に期限切れとなるべきであると規定されています。
つまり、負の Max-Age
はエラーではなく、クッキーを即座に削除するための有効な指示として解釈されるべきでした。このコミットは、Goの net/http
パッケージがこのRFCの仕様に厳密に準拠するように修正することを目的としています。これにより、他のシステムやブラウザとの互換性が向上し、標準に則ったクッキーの挙動が保証されます。
前提知識の解説
HTTPクッキー (HTTP Cookies)
HTTPクッキーは、ウェブサイトがユーザーのブラウザに保存する小さなデータのことです。主に、セッション管理(ログイン状態の維持)、パーソナライゼーション(ユーザー設定の記憶)、トラッキング(ユーザー行動の追跡)などに使用されます。
サーバーはHTTPレスポンスヘッダーの Set-Cookie
を通じてクッキーをブラウザに送信し、ブラウザは後続のリクエストで Cookie
ヘッダーを通じてそのクッキーをサーバーに送り返します。
Set-Cookie
ヘッダーと Max-Age
属性
Set-Cookie
ヘッダーは、サーバーがブラウザにクッキーを設定するために使用します。このヘッダーには、クッキーの名前と値のペアだけでなく、そのクッキーの振る舞いを制御する様々な属性を含めることができます。
Max-Age
属性は、クッキーがブラウザに保存される最大期間を秒単位で指定します。例えば、Max-Age=3600
は、クッキーが1時間(3600秒)後に期限切れになることを意味します。
RFC (Request for Comments)
RFCは、インターネット技術に関する公式な文書群です。インターネットのプロトコル、手順、プログラムなどを定義し、標準化するために使用されます。HTTPやTCP/IPなどもRFCによって定義されています。RFCは、インターネットの相互運用性を保証するための重要な基盤となります。
RFC 6265: HTTP State Management Mechanism
RFC 6265は、HTTPクッキーの動作を定義する主要な標準文書です。このRFCは、クッキーの構文、セマンティクス、およびブラウザとサーバーがクッキーをどのように処理すべきかについて詳細に記述しています。
特に、セクション5.2.2「The Max-Age Attribute」では、Max-Age
属性の処理方法について以下のように述べられています。
Max-Age
の値は、クッキーが期限切れになるまでの秒数を表す非負の整数であるべきです。- しかし、もし
Max-Age
の値が0以下の場合(負の値を含む)、ユーザーエージェント(ブラウザ)はそのクッキーを即座に期限切れとして扱うべきです。これは、クッキーを削除するためのメカニズムとして機能します。
技術的詳細
Goの net/http
パッケージは、HTTPプロトコルを扱うための強力な機能を提供します。このパッケージには、HTTPリクエストとレスポンスのパース、ルーティング、サーバーとクライアントの実装などが含まれます。
net/http/cookie.go
ファイルは、HTTPクッキーの生成、パース、および管理に関連するロジックをカプセル化しています。特に、readSetCookies
関数は、受信した Set-Cookie
ヘッダーを解析し、*Cookie
オブジェクトのリストに変換する役割を担っています。
このコミット以前の readSetCookies
関数内の Max-Age
属性のパースロジックは、strconv.Atoi
で文字列を整数に変換した後、secs < 0
という条件で負の Max-Age
値を無効と判断していました。このため、負の Max-Age
を持つクッキーはパースエラーとなり、適切に処理されませんでした。
RFC 6265のセクション5.2.2の規定により、負の Max-Age
はクッキーを即座に期限切れにするという明確な意味を持ちます。したがって、この値をエラーとして扱うのではなく、有効な指示として受け入れるようにパースロジックを変更する必要がありました。
この修正により、GoのHTTPサーバーやクライアントが、RFCに準拠したクッキーの Max-Age
処理を正しく行えるようになります。これにより、異なるシステム間でのクッキーの互換性が向上し、予期せぬクッキーの挙動が減少します。
コアとなるコードの変更箇所
--- a/src/pkg/net/http/cookie.go
+++ b/src/pkg/net/http/cookie.go
@@ -96,7 +96,7 @@ func readSetCookies(h Header) []*Cookie {
case "max-age":
secs, err := strconv.Atoi(val)
- if err != nil || secs < 0 || secs != 0 && val[0] == '0' {
+ if err != nil || secs != 0 && val[0] == '0' {
break
}
if secs <= 0 {
コアとなるコードの解説
変更は src/pkg/net/http/cookie.go
ファイルの readSetCookies
関数内、Max-Age
属性を処理する部分にあります。
元のコード:
if err != nil || secs < 0 || secs != 0 && val[0] == '0' {
break
}
修正後のコード:
if err != nil || secs != 0 && val[0] == '0' {
break
}
この変更の核心は、条件式から secs < 0
の部分が削除されたことです。
err != nil
:Max-Age
の値が整数に変換できない場合にエラーを検出します。これは引き続き必要です。secs < 0
: この条件が削除されました。 以前は、Max-Age
が負の値である場合に、そのクッキーのパースを中断していました。しかし、RFC 6265によれば、負の値はクッキーを即座に期限切れにする有効な指示であるため、これをエラーとして扱うべきではありません。secs != 0 && val[0] == '0'
: これは、Max-Age
の値が "0" 以外の数値で、かつ先頭が "0" で始まる場合(例: "0123")を検出するための条件です。このような形式は通常、数値の表現として不正とみなされるため、引き続きパースを中断します。
この変更により、Max-Age
が負の値であっても、strconv.Atoi
で正常に整数に変換されれば、パースは続行されます。その後の if secs <= 0 { ... }
のブロックで、負の値を含む0以下の Max-Age
が適切に処理され、クッキーが即座に期限切れとなるロジックが適用されます。
関連リンク
- Go CL (Change List): https://golang.org/cl/5533083
参考にした情報源リンク
- RFC 6265 - HTTP State Management Mechanism: https://datatracker.ietf.org/doc/html/rfc6265
- 特にセクション 5.2.2 "The Max-Age Attribute" を参照。
- Go
net/http
パッケージ ドキュメント: https://pkg.go.dev/net/http - Go ソースコード (GitHub): https://github.com/golang/go