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

[インデックス 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 属性は、クッキーがブラウザに保存される最大期間を秒単位で指定します。例えば、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 が適切に処理され、クッキーが即座に期限切れとなるロジックが適用されます。

関連リンク

参考にした情報源リンク