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

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

このコミットは、Go言語の標準ライブラリ net/http/httputil パッケージ内の ReverseProxy において、バックエンドからのレスポンスに含まれるホップバイホップヘッダーを適切に削除する修正を導入しています。これにより、リバースプロキシがHTTPプロトコルの仕様に準拠し、予期せぬ動作やセキュリティ上の問題を回避できるようになります。

コミット

commit 96471b65d5cbff81d47288dad5fc49ec136ccc80
Author: Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Date:   Mon Jan 27 15:24:58 2014 -0800

    httputil: in ReverseProxy, strip hop-by-hop headers from the backend response
    
    Fixes #5967.
    
    LGTM=bradfitz
    R=golang-codereviews, bradfitz
    CC=golang-codereviews
    https://golang.org/cl/57370043

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

https://github.com/golang/go/commit/96471b65d5cbff81d47288dad5fc49ec136ccc80

元コミット内容

httputil: in ReverseProxy, strip hop-by-hop headers from the backend response

このコミットは、ReverseProxy がバックエンドからのレスポンスをクライアントに転送する際に、ホップバイホップヘッダーを削除することを目的としています。これは、GoのIssue #5967を修正するものです。

変更の背景

この変更の背景には、HTTPプロトコルの「ホップバイホップヘッダー」の特性と、リバースプロキシの役割があります。

リバースプロキシは、クライアントからのリクエストを受け取り、それをバックエンドサーバーに転送し、バックエンドからのレスポンスをクライアントに返すという仲介役を担います。この際、HTTPヘッダーには「エンドツーエンドヘッダー」と「ホップバイホップヘッダー」の2種類が存在します。

  • エンドツーエンドヘッダー: リクエストの送信元から最終的な受信者まで、メッセージ全体に適用されるヘッダーです。例えば、Content-Type, Content-Length, Authorization などがあります。これらはプロキシを通過しても変更されずに転送されるべきです。
  • ホップバイホップヘッダー: 単一のTCP接続、つまり隣接するノード間(クライアントとプロキシ、またはプロキシとバックエンドサーバーなど)でのみ意味を持つヘッダーです。これらはプロキシを越えて転送されるべきではありません。例えば、Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade などがあります。

Goの net/http/httputil.ReverseProxy は、リバースプロキシとして機能しますが、以前のバージョンではバックエンドからのレスポンスに含まれるホップバイホップヘッダーを適切に削除していませんでした。このため、バックエンドから受け取ったホップバイホップヘッダーがそのままクライアントに転送されてしまい、以下のような問題を引き起こす可能性がありました。

  1. プロトコル違反: ホップバイホップヘッダーは、プロキシを越えて転送されるべきではないというHTTPの仕様に違反します。
  2. 予期せぬ動作: クライアントがこれらのヘッダーを受け取ると、誤った解釈をしたり、予期せぬ動作を引き起こしたりする可能性があります。例えば、Connection: close ヘッダーが転送されると、クライアントが接続を早期に閉じてしまうなどです。
  3. セキュリティリスク: 特定のホップバイホップヘッダーが不適切に転送されることで、情報漏洩やプロキシのバイパスなどのセキュリティ上の脆弱性につながる可能性もゼロではありません。

このコミットは、これらの問題を解決し、ReverseProxy がHTTPプロトコルの仕様に厳密に準拠するようにするために行われました。

前提知識の解説

HTTPヘッダーの種類(エンドツーエンド vs ホップバイホップ)

前述の通り、HTTPヘッダーはエンドツーエンドヘッダーとホップバイホップヘッダーに分類されます。この区別は、HTTP通信におけるプロキシの役割を理解する上で非常に重要です。

  • エンドツーエンドヘッダー: メッセージのペイロードに関する情報(例: Content-Type)、認証情報(例: Authorization)、キャッシュ制御(例: Cache-Control)など、メッセージの最終的な受信者にとって意味のある情報を含みます。これらはプロキシによって変更されるべきではありません(ただし、プロキシがキャッシュとして機能する場合など、特定の状況下では変更されることもあります)。
  • ホップバイホップヘッダー: 現在の接続に関する情報(例: Connection)、プロキシ認証(例: Proxy-Authenticate)、転送エンコーディング(例: Transfer-Encoding)など、単一のネットワークホップ(接続)にのみ関連する情報を含みます。これらのヘッダーは、プロキシが次のホップにメッセージを転送する前に削除されるか、適切に処理される必要があります。

HTTP/1.1の仕様(RFC 2616, Section 13.5.1)では、プロキシはホップバイホップヘッダーを転送してはならないと明確に規定されています。

Go言語の net/http/httputil.ReverseProxy

net/http/httputil パッケージは、HTTPユーティリティ関数を提供します。その中でも ReverseProxy は、リバースプロキシサーバーを簡単に構築するための構造体です。

ReverseProxy は、http.Handler インターフェースを実装しており、ServeHTTP メソッドを通じてHTTPリクエストを処理します。主な機能は以下の通りです。

  1. リクエストの転送: クライアントからのHTTPリクエストを、指定されたバックエンドサーバー(ターゲットURL)に転送します。この際、リクエストヘッダーの調整(例: Host ヘッダーの書き換え、X-Forwarded-For ヘッダーの追加など)が行われることがあります。
  2. レスポンスの転送: バックエンドサーバーからのHTTPレスポンスを受け取り、それをクライアントに転送します。この際も、レスポンスヘッダーの調整や、ボディのストリーミングなどが行われます。

ReverseProxy は、マイクロサービスアーキテクチャにおけるAPIゲートウェイ、ロードバランシング、SSLオフロードなど、様々な用途で利用されます。

Go言語の http.Headerhttp.ResponseWriter

  • http.Header: HTTPヘッダーを表す map[string][]string 型のエイリアスです。ヘッダー名(キー)と、そのヘッダーに関連付けられた値のリスト(スライス)を保持します。Add, Set, Get, Del などのメソッドを提供し、ヘッダーの操作を容易にします。
  • http.ResponseWriter: HTTPレスポンスを構築するために使用されるインターフェースです。Header() メソッドでレスポンスヘッダーを取得し、WriteHeader() でステータスコードを書き込み、Write() でレスポンスボディを書き込みます。

技術的詳細

このコミットの技術的詳細は、ReverseProxyServeHTTP メソッド内で、バックエンドからのレスポンスヘッダーをクライアントにコピーする前に、ホップバイホップヘッダーを明示的に削除する点にあります。

Goの net/http パッケージには、ホップバイホップヘッダーのリストを定義した内部変数 hopHeaders が存在します。このコミットでは、バックエンドからのレスポンス (res) のヘッダー (res.Header) をループ処理し、hopHeaders リストに含まれる各ヘッダー名に対応するヘッダーを res.Header.Del(h) を使って削除しています。

これにより、copyHeader(rw.Header(), res.Header) が実行される際には、すでにホップバイホップヘッダーが削除された状態のレスポンスヘッダーがクライアントにコピーされることになります。

テストケースでは、fakeHopHeader というテスト用のホップバイホップヘッダーを hopHeaders に追加し、バックエンドがこのヘッダーをレスポンスに含めた場合に、リバースプロキシがそれをクライアントに転送しないことを検証しています。

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

変更は主に2つのファイルで行われています。

  1. src/pkg/net/http/httputil/reverseproxy.go: ReverseProxyServeHTTP メソッドに、ホップバイホップヘッダーを削除するロジックが追加されました。
  2. src/pkg/net/http/httputil/reverseproxy_test.go: ホップバイホップヘッダーの削除が正しく行われることを検証するためのテストケースが追加されました。

src/pkg/net/http/httputil/reverseproxy.go の変更

--- a/src/pkg/net/http/httputil/reverseproxy.go
+++ b/src/pkg/net/http/httputil/reverseproxy.go
@@ -144,6 +144,10 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 	}\n \tdefer res.Body.Close()\n \n+\tfor _, h := range hopHeaders {\n+\t\tres.Header.Del(h)\n+\t}\n+\n \tcopyHeader(rw.Header(), res.Header)\n \n \trw.WriteHeader(res.StatusCode)\n```

### `src/pkg/net/http/httputil/reverseproxy_test.go` の変更

```diff
--- a/src/pkg/net/http/httputil/reverseproxy_test.go
+++ b/src/pkg/net/http/httputil/reverseproxy_test.go
@@ -16,6 +16,12 @@ import (\
 \t\"time\"\n )\n \n+const fakeHopHeader = \"X-Fake-Hop-Header-For-Test\"\n+\n+func init() {\n+\thopHeaders = append(hopHeaders, fakeHopHeader)\n+}\n+\n func TestReverseProxy(t *testing.T) {\n \tconst backendResponse = \"I am the backend\"\n \tconst backendStatus = 404\
@@ -36,6 +42,10 @@ func TestReverseProxy(t *ch.T) {\n \t\t\tt.Errorf(\"backend got Host header %q, want %q\", g, e)\n \t\t}\n \t\tw.Header().Set(\"X-Foo\", \"bar\")\n+\t\tw.Header().Set(\"Upgrade\", \"foo\")\n+\t\tw.Header().Set(fakeHopHeader, \"foo\")\n+\t\tw.Header().Add(\"X-Multi-Value\", \"foo\")\n+\t\tw.Header().Add(\"X-Multi-Value\", \"bar\")\n \t\thttp.SetCookie(w, &http.Cookie{Name: \"flavor\", Value: \"chocolateChip\"})\n \t\tw.WriteHeader(backendStatus)\n \t\tw.Write([]byte(backendResponse))\
@@ -64,6 +74,12 @@ func TestReverseProxy(t *testing.T) {\n \tif g, e := res.Header.Get(\"X-Foo\"), \"bar\"; g != e {\n \t\tt.Errorf(\"got X-Foo %q; expected %q\", g, e)\n \t}\n+\tif c := res.Header.Get(fakeHopHeader); c != \"\" {\n+\t\tt.Errorf(\"got %s header value %q\", fakeHopHeader, c)\n+\t}\n+\tif g, e := len(res.Header[\"X-Multi-Value\"]), 2; g != e {\n+\t\tt.Errorf(\"got %d X-Multi-Value header values; expected %d\", g, e)\n+\t}\n \tif g, e := len(res.Header[\"Set-Cookie\"]), 1; g != e {\n \t\tt.Fatalf(\"got %d SetCookies, want %d\", g, e)\n \t}\n```

## コアとなるコードの解説

### `reverseproxy.go` の変更点

```go
	for _, h := range hopHeaders {
		res.Header.Del(h)
	}

この4行が、このコミットの核心となる変更です。

  • hopHeaders: これは net/http パッケージ内部で定義されている、ホップバイホップヘッダー名の文字列スライスです。通常、Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade などが含まれます。
  • for _, h := range hopHeaders: hopHeaders スライス内の各ヘッダー名 h に対してループ処理を行います。
  • res.Header.Del(h): バックエンドからのレスポンス res のヘッダーマップ (res.Header) から、現在のホップバイホップヘッダー h を削除します。Del メソッドは、指定されたキー(ヘッダー名)に対応するすべての値を削除します。

このコードブロックは、バックエンドからのレスポンスボディを読み込んだ直後、かつレスポンスヘッダーをクライアントにコピーする copyHeader 関数の呼び出し直前に配置されています。これにより、クライアントにレスポンスが送信される前に、不要なホップバイホップヘッダーが確実に除去されます。

reverseproxy_test.go の変更点

テストファイルでは、以下の点が重要です。

  1. const fakeHopHeader = "X-Fake-Hop-Header-For-Test": テスト専用のカスタムホップバイホップヘッダーを定義しています。
  2. func init() { hopHeaders = append(hopHeaders, fakeHopHeader) }: init 関数内で、この fakeHopHeader を実際の hopHeaders リストに追加しています。これにより、テスト中にこのカスタムヘッダーもホップバイホップヘッダーとして扱われるようになります。
  3. バックエンドサーバーのハンドラ内で、w.Header().Set("Upgrade", "foo")w.Header().Set(fakeHopHeader, "foo") のように、意図的にホップバイホップヘッダーをレスポンスに追加しています。
  4. クライアント側でのレスポンス検証で、if c := res.Header.Get(fakeHopHeader); c != "" { ... } のように、fakeHopHeader がレスポンスヘッダーに含まれていないことを確認しています。もし含まれていればテストは失敗し、リバースプロキシがホップバイホップヘッダーを正しく削除していないことを示します。

これらのテストの追加により、ReverseProxy がホップバイホップヘッダーを適切に処理するという振る舞いが保証されるようになりました。

関連リンク

参考にした情報源リンク

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

このコミットは、Go言語の標準ライブラリ net/http/httputil パッケージ内の ReverseProxy において、バックエンドからのレスポンスに含まれるホップバイホップヘッダーを適切に削除する修正を導入しています。これにより、リバースプロキシがHTTPプロトコルの仕様に準拠し、予期せぬ動作やセキュリティ上の問題を回避できるようになります。

コミット

commit 96471b65d5cbff81d47288dad5fc49ec136ccc80
Author: Fredrik Enestad <fredrik.enestad@soundtrackyourbrand.com>
Date:   Mon Jan 27 15:24:58 2014 -0800

    httputil: in ReverseProxy, strip hop-by-hop headers from the backend response
    
    Fixes #5967.
    
    LGTM=bradfitz
    R=golang-codereviews, bradfitz
    CC=golang-codereviews
    https://golang.org/cl/57370043

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

https://github.com/golang/go/commit/96471b65d5cbff81d47288dad5fc49ec136ccc80

元コミット内容

httputil: in ReverseProxy, strip hop-by-hop headers from the backend response

このコミットは、ReverseProxy がバックエンドからのレスポンスをクライアントに転送する際に、ホップバイホップヘッダーを削除することを目的としています。これは、GoのIssue #5967を修正するものです。

変更の背景

この変更の背景には、HTTPプロトコルの「ホップバイホップヘッダー」の特性と、リバースプロキシの役割があります。

リバースプロキシは、クライアントからのリクエストを受け取り、それをバックエンドサーバーに転送し、バックエンドからのレスポンスをクライアントに返すという仲介役を担います。この際、HTTPヘッダーには「エンドツーエンドヘッダー」と「ホップバイホップヘッダー」の2種類が存在します。

  • エンドツーエンドヘッダー: リクエストの送信元から最終的な受信者まで、メッセージ全体に適用されるヘッダーです。例えば、Content-Type, Content-Length, Authorization などがあります。これらはプロキシを通過しても変更されずに転送されるべきです。
  • ホップバイホップヘッダー: 単一のTCP接続、つまり隣接するノード間(クライアントとプロキシ、またはプロキシとバックエンドサーバーなど)でのみ意味を持つヘッダーです。これらはプロキシを越えて転送されるべきではありません。例えば、Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade などがあります。

Goの net/http/httputil.ReverseProxy は、リバースプロキシとして機能しますが、以前のバージョンではバックエンドからのレスポンスに含まれるホップバイホップヘッダーを適切に削除していませんでした。このため、バックエンドから受け取ったホップバイホップヘッダーがそのままクライアントに転送されてしまい、以下のような問題を引き起こす可能性がありました。

  1. プロトコル違反: ホップバイホップヘッダーは、プロキシを越えて転送されるべきではないというHTTPの仕様に違反します。
  2. 予期せぬ動作: クライアントがこれらのヘッダーを受け取ると、誤った解釈をしたり、予期せぬ動作を引き起こしたりする可能性があります。例えば、Connection: close ヘッダーが転送されると、クライアントが接続を早期に閉じてしまうなどです。
  3. セキュリティリスク: 特定のホップバイホップヘッダーが不適切に転送されることで、情報漏洩やプロキシのバイパスなどのセキュリティ上の脆弱性につながる可能性もゼロではありません。

このコミットは、これらの問題を解決し、ReverseProxy がHTTPプロトコルの仕様に厳密に準拠するようにするために行われました。

前提知識の解説

HTTPヘッダーの種類(エンドツーエンド vs ホップバイホップ)

前述の通り、HTTPヘッダーはエンドツーエンドヘッダーとホップバイホップヘッダーに分類されます。この区別は、HTTP通信におけるプロキシの役割を理解する上で非常に重要です。

  • エンドツーエンドヘッダー: メッセージのペイロードに関する情報(例: Content-Type)、認証情報(例: Authorization)、キャッシュ制御(例: Cache-Control)など、メッセージの最終的な受信者にとって意味のある情報を含みます。これらはプロキシによって変更されるべきではありません(ただし、プロキシがキャッシュとして機能する場合など、特定の状況下では変更されることもあります)。
  • ホップバイホップヘッダー: 現在の接続に関する情報(例: Connection)、プロキシ認証(例: Proxy-Authenticate)、転送エンコーディング(例: Transfer-Encoding)など、単一のネットワークホップ(接続)にのみ関連する情報を含みます。これらのヘッダーは、プロキシが次のホップにメッセージを転送する前に削除されるか、適切に処理される必要があります。

HTTP/1.1の仕様(RFC 2616, Section 13.5.1)では、プロキシはホップバイホップヘッダーを転送してはならないと明確に規定されています。

Go言語の net/http/httputil.ReverseProxy

net/http/httputil パッケージは、HTTPユーティリティ関数を提供します。その中でも ReverseProxy は、リバースプロキシサーバーを簡単に構築するための構造体です。

ReverseProxy は、http.Handler インターフェースを実装しており、ServeHTTP メソッドを通じてHTTPリクエストを処理します。主な機能は以下の通りです。

  1. リクエストの転送: クライアントからのHTTPリクエストを、指定されたバックエンドサーバー(ターゲットURL)に転送します。この際、リクエストヘッダーの調整(例: Host ヘッダーの書き換え、X-Forwarded-For ヘッダーの追加など)が行われることがあります。
  2. レスポンスの転送: バックエンドサーバーからのHTTPレスポンスを受け取り、それをクライアントに転送します。この際も、レスポンスヘッダーの調整や、ボディのストリーミングなどが行われます。

ReverseProxy は、マイクロサービスアーキテクチャにおけるAPIゲートウェイ、ロードバランシング、SSLオフロードなど、様々な用途で利用されます。

Go言語の http.Headerhttp.ResponseWriter

  • http.Header: HTTPヘッダーを表す map[string][]string 型のエイリアスです。ヘッダー名(キー)と、そのヘッダーに関連付けられた値のリスト(スライス)を保持します。Add, Set, Get, Del などのメソッドを提供し、ヘッダーの操作を容易にします。
  • http.ResponseWriter: HTTPレスポンスを構築するために使用されるインターフェースです。Header() メソッドでレスポンスヘッダーを取得し、WriteHeader() でステータスコードを書き込み、Write() でレスポンスボディを書き込みます。

技術的詳細

このコミットの技術的詳細は、ReverseProxyServeHTTP メソッド内で、バックエンドからのレスポンスヘッダーをクライアントにコピーする前に、ホップバイホップヘッダーを明示的に削除する点にあります。

Goの net/http パッケージには、ホップバイホップヘッダーのリストを定義した内部変数 hopHeaders が存在します。このコミットでは、バックエンドからのレスポンス (res) のヘッダー (res.Header) をループ処理し、hopHeaders リストに含まれる各ヘッダー名に対応するヘッダーを res.Header.Del(h) を使って削除しています。

これにより、copyHeader(rw.Header(), res.Header) が実行される際には、すでにホップバイホップヘッダーが削除された状態のレスポンスヘッダーがクライアントにコピーされることになります。

テストケースでは、fakeHopHeader というテスト用のホップバイホップヘッダーを hopHeaders に追加し、バックエンドがこのヘッダーをレスポンスに含めた場合に、リバースプロキシがそれをクライアントに転送しないことを検証しています。

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

変更は主に2つのファイルで行われています。

  1. src/pkg/net/http/httputil/reverseproxy.go: ReverseProxyServeHTTP メソッドに、ホップバイホップヘッダーを削除するロジックが追加されました。
  2. src/pkg/net/http/httputil/reverseproxy_test.go: ホップバイホップヘッダーの削除が正しく行われることを検証するためのテストケースが追加されました。

src/pkg/net/http/httputil/reverseproxy.go の変更

--- a/src/pkg/net/http/httputil/reverseproxy.go
+++ b/src/pkg/net/http/httputil/reverseproxy.go
@@ -144,6 +144,10 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 	}\n \tdefer res.Body.Close()\n \n+\tfor _, h := range hopHeaders {\n+\t\tres.Header.Del(h)\n+\t}\n+\n \tcopyHeader(rw.Header(), res.Header)\n \n \trw.WriteHeader(res.StatusCode)\

src/pkg/net/http/httputil/reverseproxy_test.go の変更

--- a/src/pkg/net/http/httputil/reverseproxy_test.go
+++ b/src/pkg/net/http/httputil/reverseproxy_test.go
@@ -16,6 +16,12 @@ import (\
 \t\"time\"\n )\n \n+const fakeHopHeader = \"X-Fake-Hop-Header-For-Test\"\n+\n+func init() {\n+\thopHeaders = append(hopHeaders, fakeHopHeader)\n+}\n+\n func TestReverseProxy(t *testing.T) {\n \tconst backendResponse = \"I am the backend\"\n \tconst backendStatus = 404\
@@ -36,6 +42,10 @@ func TestReverseProxy(t *ch.T) {\n \t\t\tt.Errorf(\"backend got Host header %q, want %q\", g, e)\n \t\t}\n \t\tw.Header().Set(\"X-Foo\", \"bar\")\n+\t\tw.Header().Set(\"Upgrade\", \"foo\")\n+\t\tw.Header().Set(fakeHopHeader, \"foo\")\n+\t\tw.Header().Add(\"X-Multi-Value\", \"foo\")\n+\t\tw.Header().Add(\"X-Multi-Value\", \"bar\")\n \t\thttp.SetCookie(w, &http.Cookie{Name: \"flavor\", Value: \"chocolateChip\"})\n \t\tw.WriteHeader(backendStatus)\n \t\tw.Write([]byte(backendResponse))\
@@ -64,6 +74,12 @@ func TestReverseProxy(t *testing.T) {\n \tif g, e := res.Header.Get(\"X-Foo\"), \"bar\"; g != e {\n \t\tt.Errorf(\"got X-Foo %q; expected %q\", g, e)\n \t}\n+\tif c := res.Header.Get(fakeHopHeader); c != \"\" {\n+\t\tt.Errorf(\"got %s header value %q\", fakeHopHeader, c)\n+\t}\n+\tif g, e := len(res.Header[\"X-Multi-Value\"]), 2; g != e {\n+\t\tt.Errorf(\"got %d X-Multi-Value header values; expected %d\", g, e)\n+\t}\n \tif g, e := len(res.Header[\"Set-Cookie\"]), 1; g != e {\n \t\tt.Fatalf(\"got %d SetCookies, want %d\", g, e)\n \t}\n```

## コアとなるコードの解説

### `reverseproxy.go` の変更点

```go
	for _, h := range hopHeaders {
		res.Header.Del(h)
	}

この4行が、このコミットの核心となる変更です。

  • hopHeaders: これは net/http パッケージ内部で定義されている、ホップバイホップヘッダー名の文字列スライスです。通常、Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailers, Transfer-Encoding, Upgrade などが含まれます。
  • for _, h := range hopHeaders: hopHeaders スライス内の各ヘッダー名 h に対してループ処理を行います。
  • res.Header.Del(h): バックエンドからのレスポンス res のヘッダーマップ (res.Header) から、現在のホップバイホップヘッダー h を削除します。Del メソッドは、指定されたキー(ヘッダー名)に対応するすべての値を削除します。

このコードブロックは、バックエンドからのレスポンスボディを読み込んだ直後、かつレスポンスヘッダーをクライアントにコピーする copyHeader 関数の呼び出し直前に配置されています。これにより、クライアントにレスポンスが送信される前に、不要なホップバイホップヘッダーが確実に除去されます。

reverseproxy_test.go の変更点

テストファイルでは、以下の点が重要です。

  1. const fakeHopHeader = "X-Fake-Hop-Header-For-Test": テスト専用のカスタムホップバイホップヘッダーを定義しています。
  2. func init() { hopHeaders = append(hopHeaders, fakeHopHeader) }: init 関数内で、この fakeHopHeader を実際の hopHeaders リストに追加しています。これにより、テスト中にこのカスタムヘッダーもホップバイホップヘッダーとして扱われるようになります。
  3. バックエンドサーバーのハンドラ内で、w.Header().Set("Upgrade", "foo")w.Header().Set(fakeHopHeader, "foo") のように、意図的にホップバイホップヘッダーをレスポンスに追加しています。
  4. クライアント側でのレスポンス検証で、if c := res.Header.Get(fakeHopHeader); c != "" { ... } のように、fakeHopHeader がレスポンスヘッダーに含まれていないことを確認しています。もし含まれていればテストは失敗し、リバースプロキシがホップバイホップヘッダーを正しく削除していないことを示します。

これらのテストの追加により、ReverseProxy がホップバイホップヘッダーを適切に処理するという振る舞いが保証されるようになりました。

関連リンク

参考にした情報源リンク