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

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

このコミットは、Go言語の標準ライブラリである net/http パッケージにおいて、HTTPクライアントがPOSTリクエストに対するレスポンスで受け取ったCookieを適切に処理するように修正するものです。具体的には、POSTリクエストの応答で設定されたCookieがクライアントのCookieジャー(Cookieを保存・管理する場所)に保存されるようになります。これにより、GETリクエストと同様にPOSTリクエストでもCookieベースのセッション管理が正しく機能するようになります。

コミット

net/http: set cookies in client jar on POST requests.

Cookies recieved in a response to a POST request are stored
in the client's jar like they are for GET requests.

R=golang-dev, rsc
CC=bradfitz, golang-dev
https://golang.org/cl/5576065

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

https://github.com/golang/go/commit/d91ade02e7c0272fe144bedb92601ed00271d372

元コミット内容

commit d91ade02e7c0272fe144bedb92601ed00271d372
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date:   Sun Jan 29 14:16:11 2012 -0500

    net/http: set cookies in client jar on POST requests.
    
    Cookies recieved in a response to a POST request are stored
    in the client's jar like they are for GET requests.
    
    R=golang-dev, rsc
    CC=bradfitz, golang-dev
    https://golang.org/cl/5576065

変更の背景

この変更が行われる前は、Goの net/http クライアントは、GETリクエストに対するレスポンスで受け取ったCookieは適切にCookieジャーに保存していましたが、POSTリクエストに対するレスポンスで受け取ったCookieは保存していませんでした。これは、Webアプリケーションにおけるセッション管理において問題を引き起こす可能性がありました。

多くのWebアプリケーションでは、ユーザーがログインフォーム(通常はPOSTリクエスト)を送信した後、サーバーはセッションIDを含むCookieをクライアントに発行し、その後のリクエストでそのCookieを使用してユーザーを認証・識別します。もしPOSTリクエストの応答で受け取ったCookieが保存されない場合、ログイン後のセッションが維持されず、ユーザーは再度認証を求められるか、アプリケーションの機能が正しく動作しないという問題が発生します。

このコミットは、このような不整合を解消し、POSTリクエストでもGETリクエストと同様にCookieが適切に扱われるようにすることで、net/http クライアントの堅牢性と実用性を向上させることを目的としています。

前提知識の解説

HTTP Cookieは、WebサーバーがユーザーのWebブラウザに送信する小さなデータの一部です。ブラウザはそれらを保存し、同じサーバーへの後続のリクエストとともに送り返します。Cookieは主に以下の目的で使用されます。

  • セッション管理: ログイン状態の維持、ショッピングカートの内容、ゲームのスコアなど。
  • パーソナライゼーション: ユーザー設定、テーマ、その他の設定。
  • トラッキング: ユーザーの行動追跡、広告のターゲティング。

CookieはHTTPレスポンスヘッダーの Set-Cookie フィールドによってサーバーからクライアントに送信され、HTTPリクエストヘッダーの Cookie フィールドによってクライアントからサーバーに送信されます。

Go言語の net/http パッケージ

net/http はGo言語の標準ライブラリであり、HTTPクライアントとサーバーの実装を提供します。Webアプリケーションの構築やHTTPリクエストの送信に広く使用されます。

  • http.Client: HTTPリクエストを送信するためのクライアント構造体です。この構造体を通じて、GET、POSTなどのHTTPメソッドを実行できます。
  • http.Request: HTTPリクエストを表す構造体です。URL、メソッド、ヘッダー、ボディなどの情報を含みます。
  • http.Response: HTTPレスポンスを表す構造体です。ステータスコード、ヘッダー、ボディ、そしてサーバーから送られてきたCookieなどの情報を含みます。
  • http.CookieJar インターフェース: クライアントがCookieを保存および取得するためのインターフェースです。net/http/cookiejar パッケージには、このインターフェースのデフォルト実装(メモリベースのCookieジャー)が提供されています。http.ClientJar フィールドに http.CookieJar の実装を設定することで、クライアントは自動的にCookieを管理するようになります。
  • Response.Cookies() メソッド: http.Response オブジェクトのメソッドで、レスポンスヘッダーに含まれる Set-Cookie フィールドから解析された *http.Cookie のスライスを返します。

技術的詳細

このコミットの技術的な核心は、http.ClientPost メソッド内で、レスポンスから受け取ったCookieをクライアントの Jar に明示的に設定する処理を追加した点にあります。

Goの net/http パッケージにおける http.Client は、Jar フィールドに http.CookieJar インターフェースの実装が設定されている場合、通常は自動的にCookieを管理します。しかし、このコミット以前の Post メソッドの実装では、send 関数(内部的にリクエストを送信しレスポンスを受け取る関数)の戻り値をそのまま返しており、レスポンスからCookieを抽出し、それをクライアントの Jar に追加する明示的なステップが欠けていました。

GETリクエストを処理する Get メソッドなどでは、このCookieの自動処理が適切に行われていた可能性がありますが、Post メソッドではそのロジックが不足していたため、POSTリクエストの応答でサーバーが Set-Cookie ヘッダーを送信しても、クライアントはそれを永続化せず、後続のリクエストでそのCookieを送信することができませんでした。

この修正により、Post メソッドは send 関数からレスポンスを受け取った後、c.Jar != nil (クライアントにCookieジャーが設定されているか)を確認し、設定されていれば r.Cookies() を呼び出してレスポンスからCookieのリストを取得し、そのリストを c.Jar.SetCookies(req.URL, r.Cookies()) を使ってCookieジャーに保存します。これにより、POSTリクエストに対するCookieの処理がGETリクエストと同様に一貫性を持つようになります。

http.CookieJar インターフェースの SetCookies メソッドは、指定されたURLとCookieのリストを受け取り、それらをジャーに保存する役割を担います。この修正によって、POSTリクエスト後のセッション管理が正しく機能するようになり、より複雑なWebアプリケーションとの連携が可能になります。

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

変更は src/pkg/net/http/client.go ファイルの Client 構造体の Post メソッド内で行われています。

--- a/src/pkg/net/http/client.go
+++ b/src/pkg/net/http/client.go
@@ -274,7 +274,11 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response,
 		return nil, err
 	}\n     req.Header.Set("Content-Type", bodyType)\n-	return send(req, c.Transport)\n+\tr, err = send(req, c.Transport)\n+\tif c.Jar != nil {\n+\t\tc.Jar.SetCookies(req.URL, r.Cookies())\n+\t}\n+\treturn r, err
 }\n
 // PostForm issues a POST to the specified URL,

コアとなるコードの解説

変更前の Post メソッドの関連部分は以下のようになっていました。

	req.Header.Set("Content-Type", bodyType)
	return send(req, c.Transport)

ここで send(req, c.Transport) はHTTPリクエストを送信し、そのレスポンスを返します。しかし、この戻り値が直接 Post メソッドの戻り値として返されるため、レスポンスに含まれるCookieをクライアントの Jar に保存する処理が実行されていませんでした。

変更後のコードは以下のようになっています。

	req.Header.Set("Content-Type", bodyType)
	r, err = send(req, c.Transport) // send関数からの戻り値を一旦変数rとerrに格納
	if c.Jar != nil {               // クライアントにCookieジャーが設定されているか確認
		c.Jar.SetCookies(req.URL, r.Cookies()) // レスポンスからCookieを取得し、ジャーに保存
	}
	return r, err                   // レスポンスとエラーを返す

この変更により、send 関数から返された *http.Response オブジェクト r が一時的に保持され、その r から r.Cookies() メソッドを使ってレスポンスに含まれるCookieが抽出されます。そして、クライアントの Jarnil でない(つまり、Cookieジャーが有効になっている)場合に、c.Jar.SetCookies(req.URL, r.Cookies()) を呼び出して、これらのCookieがクライアントのCookieジャーに保存されるようになりました。

この修正は、net/http クライアントがHTTPプロトコルにおけるCookieのセマンティクスをより完全に遵守し、POSTリクエストを含むすべてのHTTPメソッドで一貫したCookie管理を行うために不可欠でした。

関連リンク

参考にした情報源リンク

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

このコミットは、Go言語の標準ライブラリである net/http パッケージにおいて、HTTPクライアントがPOSTリクエストに対するレスポンスで受け取ったCookieを適切に処理するように修正するものです。具体的には、POSTリクエストの応答で設定されたCookieがクライアントのCookieジャー(Cookieを保存・管理する場所)に保存されるようになります。これにより、GETリクエストと同様にPOSTリクエストでもCookieベースのセッション管理が正しく機能するようになります。

コミット

net/http: set cookies in client jar on POST requests.

Cookies recieved in a response to a POST request are stored
in the client's jar like they are for GET requests.

R=golang-dev, rsc
CC=bradfitz, golang-dev
https://golang.org/cl/5576065

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

https://github.com/golang/go/commit/d91ade02e7c0272fe144bedb92601ed00271d372

元コミット内容

commit d91ade02e7c0272fe144bedb92601ed00271d372
Author: Volker Dobler <dr.volker.dobler@gmail.com>
Date:   Sun Jan 29 14:16:11 2012 -0500

    net/http: set cookies in client jar on POST requests.
    
    Cookies recieved in a response to a POST request are stored
    in the client's jar like they are for GET requests.
    
    R=golang-dev, rsc
    CC=bradfitz, golang-dev
    https://golang.org/cl/5576065

変更の背景

この変更が行われる前は、Goの net/http クライアントは、GETリクエストに対するレスポンスで受け取ったCookieは適切にCookieジャーに保存していましたが、POSTリクエストに対するレスポンスで受け取ったCookieは保存していませんでした。これは、Webアプリケーションにおけるセッション管理において問題を引き起こす可能性がありました。

多くのWebアプリケーションでは、ユーザーがログインフォーム(通常はPOSTリクエスト)を送信した後、サーバーはセッションIDを含むCookieをクライアントに発行し、その後のリクエストでそのCookieを使用してユーザーを認証・識別します。もしPOSTリクエストの応答で受け取ったCookieが保存されない場合、ログイン後のセッションが維持されず、ユーザーは再度認証を求められるか、アプリケーションの機能が正しく動作しないという問題が発生します。

このコミットは、このような不整合を解消し、POSTリクエストでもGETリクエストと同様にCookieが適切に扱われるようにすることで、net/http クライアントの堅牢性と実用性を向上させることを目的としています。

前提知識の解説

HTTP Cookieは、WebサーバーがユーザーのWebブラウザに送信する小さなデータの一部です。ブラウザはそれらを保存し、同じサーバーへの後続のリクエストとともに送り返します。Cookieは主に以下の目的で使用されます。

  • セッション管理: ログイン状態の維持、ショッピングカートの内容、ゲームのスコアなど。
  • パーソナライゼーション: ユーザー設定、テーマ、その他の設定。
  • トラッキング: ユーザーの行動追跡、広告のターゲティング。

CookieはHTTPレスポンスヘッダーの Set-Cookie フィールドによってサーバーからクライアントに送信され、HTTPリクエストヘッダーの Cookie フィールドによってクライアントからサーバーに送信されます。

Go言語の net/http パッケージ

net/http はGo言語の標準ライブラリであり、HTTPクライアントとサーバーの実装を提供します。Webアプリケーションの構築やHTTPリクエストの送信に広く使用されます。

  • http.Client: HTTPリクエストを送信するためのクライアント構造体です。この構造体を通じて、GET、POSTなどのHTTPメソッドを実行できます。
  • http.Request: HTTPリクエストを表す構造体です。URL、メソッド、ヘッダー、ボディなどの情報を含みます。
  • http.Response: HTTPレスポンスを表す構造体です。ステータスコード、ヘッダー、ボディ、そしてサーバーから送られてきたCookieなどの情報を含みます。
  • http.CookieJar インターフェース: クライアントがCookieを保存および取得するためのインターフェースです。net/http/cookiejar パッケージには、このインターフェースのデフォルト実装(メモリベースのCookieジャー)が提供されています。http.ClientJar フィールドに http.CookieJar の実装を設定することで、クライアントは自動的にCookieを管理するようになります。
  • Response.Cookies() メソッド: http.Response オブジェクトのメソッドで、レスポンスヘッダーに含まれる Set-Cookie フィールドから解析された *http.Cookie のスライスを返します。

技術的詳細

このコミットの技術的な核心は、http.ClientPost メソッド内で、レスポンスから受け取ったCookieをクライアントの Jar に明示的に設定する処理を追加した点にあります。

Goの net/http パッケージにおける http.Client は、Jar フィールドに http.CookieJar インターフェースの実装が設定されている場合、通常は自動的にCookieを管理します。しかし、このコミット以前の Post メソッドの実装では、send 関数(内部的にリクエストを送信しレスポンスを受け取る関数)の戻り値をそのまま返しており、レスポンスからCookieを抽出し、それをクライアントの Jar に追加する明示的なステップが欠けていました。

GETリクエストを処理する Get メソッドなどでは、このCookieの自動処理が適切に行われていた可能性がありますが、Post メソッドではそのロジックが不足していたため、POSTリクエストの応答でサーバーが Set-Cookie ヘッダーを送信しても、クライアントはそれを永続化せず、後続のリクエストでそのCookieを送信することができませんでした。

この修正により、Post メソッドは send 関数からレスポンスを受け取った後、c.Jar != nil (クライアントにCookieジャーが設定されているか)を確認し、設定されていれば r.Cookies() を呼び出してレスポンスからCookieのリストを取得し、そのリストを c.Jar.SetCookies(req.URL, r.Cookies()) を使ってCookieジャーに保存します。これにより、POSTリクエストに対するCookieの処理がGETリクエストと同様に一貫性を持つようになります。

http.CookieJar インターフェースの SetCookies メソッドは、指定されたURLとCookieのリストを受け取り、それらをジャーに保存する役割を担います。この修正によって、POSTリクエスト後のセッション管理が正しく機能するようになり、より複雑なWebアプリケーションとの連携が可能になります。

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

変更は src/pkg/net/http/client.go ファイルの Client 構造体の Post メソッド内で行われています。

--- a/src/pkg/net/http/client.go
+++ b/src/pkg/net/http/client.go
@@ -274,7 +274,11 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response,
 		return nil, err
 	}\n     req.Header.Set("Content-Type", bodyType)\n-	return send(req, c.Transport)\n+\tr, err = send(req, c.Transport)\n+\tif c.Jar != nil {\n+\t\tc.Jar.SetCookies(req.URL, r.Cookies())\n+\t}\n+\treturn r, err
 }\n
 // PostForm issues a POST to the specified URL,

コアとなるコードの解説

変更前の Post メソッドの関連部分は以下のようになっていました。

	req.Header.Set("Content-Type", bodyType)
	return send(req, c.Transport)

ここで send(req, c.Transport) はHTTPリクエストを送信し、そのレスポンスを返します。しかし、この戻り値が直接 Post メソッドの戻り値として返されるため、レスポンスに含まれるCookieをクライアントの Jar に保存する処理が実行されていませんでした。

変更後のコードは以下のようになっています。

	req.Header.Set("Content-Type", bodyType)
	r, err = send(req, c.Transport) // send関数からの戻り値を一旦変数rとerrに格納
	if c.Jar != nil {               // クライアントにCookieジャーが設定されているか確認
		c.Jar.SetCookies(req.URL, r.Cookies()) // レスポンスからCookieを取得し、ジャーに保存
	}
	return r, err                   // レスポンスとエラーを返す

この変更により、send 関数から返された *http.Response オブジェクト r が一時的に保持され、その r から r.Cookies() メソッドを使ってレスポンスに含まれるCookieが抽出されます。そして、クライアントの Jarnil でない(つまり、Cookieジャーが有効になっている)場合に、c.Jar.SetCookies(req.URL, r.Cookies()) を呼び出して、これらのCookieがクライアントのCookieジャーに保存されるようになりました。

この修正は、net/http クライアントがHTTPプロトコルにおけるCookieのセマンティクスをより完全に遵守し、POSTリクエストを含むすべてのHTTPメソッドで一貫したCookie管理を行うために不可欠でした。

関連リンク

参考にした情報源リンク