github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/net/http/httputil/reverseproxy.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // HTTP逆プロキシハンドラ
     6  
     7  package httputil
     8  
     9  import (
    10  	"github.com/shogo82148/std/log"
    11  	"github.com/shogo82148/std/net/http"
    12  	"github.com/shogo82148/std/net/url"
    13  	"github.com/shogo82148/std/time"
    14  )
    15  
    16  // ProxyRequestは、[ReverseProxy] によって書き換えられるリクエストを含んでいます。
    17  type ProxyRequest struct {
    18  	In *http.Request
    19  
    20  	// Outはプロキシに送信されるリクエストです。
    21  	// Rewrite関数はこのリクエストを変更または置換する場合があります。
    22  	// Rewriteが呼び出される前に、ホップバイホップのヘッダーはこのリクエストから削除されます。
    23  	Out *http.Request
    24  }
    25  
    26  // SetURLは、ターゲットに指定されたスキーム、ホスト、およびベースパスに従って、アウトバウンドリクエストをルーティングします。
    27  // もしターゲットのパスが"/base"であり、受信したリクエストが"/dir"である場合、ターゲットリクエストは"/base/dir"となります。
    28  //
    29  // SetURLは、アウトバウンドのHostヘッダをターゲットのホストに合わせて書き換えます。
    30  // インバウンドのリクエストのHostヘッダを保持するために([NewSingleHostReverseProxy] のデフォルトの動作):
    31  //
    32  //	rewriteFunc := func(r *httputil.ProxyRequest) {
    33  //	    r.SetURL(url)
    34  //	    r.Out.Host = r.In.Host
    35  //	}
    36  func (r *ProxyRequest) SetURL(target *url.URL)
    37  
    38  // SetXForwardedは、出力リクエストのX-Forwarded-For、X-Forwarded-Host、およびX-Forwarded-Protoヘッダーを設定します。
    39  //
    40  // - X-Forwarded-Forヘッダーは、クライアントのIPアドレスに設定されます。
    41  // - X-Forwarded-Hostヘッダーは、クライアントが要求したホスト名に設定されます。
    42  // - X-Forwarded-Protoヘッダーは、入力リクエストがTLS対応の接続で行われたかどうかに応じて、「http」または「https」に設定されます。
    43  //
    44  // 出力リクエストに既存のX-Forwarded-Forヘッダーが含まれている場合、SetXForwardedはクライアントのIPアドレスを追加します。
    45  // SetXForwardedを呼び出す前に、入力リクエストのX-Forwarded-Forヘッダー(Director関数を使用して [ReverseProxy] を使用している場合のデフォルト動作)をコピーして、
    46  // 入力リクエストのX-Forwarded-Forヘッダーに追加します:
    47  //
    48  //	rewriteFunc := func(r *httputil.ProxyRequest) {
    49  //	   r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"]
    50  //	   r.SetXForwarded()
    51  //	}
    52  func (r *ProxyRequest) SetXForwarded()
    53  
    54  // ReverseProxyは、受信したリクエストを別のサーバーに送信し、レスポンスをクライアントにプロキシするHTTPハンドラです。
    55  //
    56  // もし基礎となるトランスポートがClientTrace.Got1xxResponseをサポートしている場合、1xxのレスポンスはクライアントに転送されます。
    57  type ReverseProxy struct {
    58  
    59  	// Rewriteは、リクエストを変更してTransportを使用して送信される新しいリクエストに変換する関数でなければなりません。
    60  	// そのレスポンスは、元のクライアントに変更せずにコピーされます。
    61  	// Rewriteは、戻る後に提供されたProxyRequestまたはその内容にアクセスしてはいけません。
    62  	//
    63  	// Forwarded、X-Forwarded、X-Forwarded-Host、およびX-Forwarded-Protoヘッダーは、
    64  	// Rewriteが呼び出される前に送信リクエストから削除されます。また、ProxyRequest.SetXForwardedメソッドも参照してください。
    65  	//
    66  	// 解析できないクエリパラメータは、Rewriteが呼び出される前に送信リクエストから削除されます。
    67  	// Rewrite関数は、インバウンドURLのRawQueryをアウトバウンドURLにコピーして、元のパラメータ文字列を保持することがあります。
    68  	// 注意:これは、プロキシのクエリパラメータの解釈がダウンストリームサーバーと一致しない場合にセキュリティの問題を引き起こす可能性があります。
    69  	//
    70  	// RewriteまたはDirectorのいずれか一つのみ設定できます。
    71  	Rewrite func(*ProxyRequest)
    72  
    73  	// Director(ディレクター)は、リクエストを変更して新しいリクエストをTransport(トランスポート)を使用して送信します。そのレスポンスは、元のクライアントに変更せずにコピーされます。Directorは、戻った後に提供されたリクエストにアクセスしてはいけません。
    74  	// デフォルトでは、X-Forwarded-ForヘッダーはクライアントのIPアドレスの値に設定されます。もし既にX-Forwarded-Forヘッダーが存在する場合、クライアントのIPは既存の値に追加されます。ただし、特殊なケースとして、リクエストのRequest.Headerマップにヘッダーが存在しているが、値がnilである場合(Director関数によって設定された場合など)、X-Forwarded-Forヘッダーは変更されません。
    75  	// IPスプーフィングを防ぐために、クライアントまたは信頼できないプロキシから送られてきたプリエクスティングのX-Forwarded-Forヘッダーを削除するようにしてください。
    76  	// ディレクターが戻った後にリクエストからホップバイホップヘッダーが削除されます。これにより、ディレクターが追加したヘッダーも削除される可能性があります。リクエストの変更を保持するためには、リライト関数を使用してください。
    77  	// ディレクターが戻った後、リクエストのRequest.Formが設定されている場合は、解析できないクエリパラメータが送信先のリクエストから削除されます。
    78  	// RewriteまたはDirectorのうち、最大1つが設定できます。
    79  	Director func(*http.Request)
    80  
    81  	// プロキシリクエストを実行するために使用されるトランスポートです。
    82  	// nil の場合、http.DefaultTransport が使用されます。
    83  	Transport http.RoundTripper
    84  
    85  	// FlushIntervalは、レスポンスボディをクライアントにコピーする際のフラッシュ間隔を指定します。
    86  	// ゼロの場合、定期的なフラッシュは行われません。
    87  	// 負の値は、クライアントへの各書き込みの直後にすぐにフラッシュすることを意味します。
    88  	// FlushIntervalは、ReverseProxyがストリーミングレスポンスとしてレスポンスを認識するか、またはContentLengthが-1の場合は無視されます。
    89  	// このようなレスポンスの場合、書き込みはすぐにクライアントにフラッシュされます。
    90  	FlushInterval time.Duration
    91  
    92  	// ErrorLogは、リクエストをプロキシする際に発生したエラーのオプションのロガーを指定します。
    93  	// nilの場合、ログはlogパッケージの標準ロガーを使用して行われます。
    94  	ErrorLog *log.Logger
    95  
    96  	// BufferPoolは、io.CopyBufferがHTTPのレスポンスボディをコピーする際に使用するバイトスライスを取得するためのオプションのバッファプールを指定します。
    97  	BufferPool BufferPool
    98  
    99  	// ModifyResponseはオプションの関数であり、バックエンドからのレスポンスを変更する役割を持ちます。
   100  	// この関数は、バックエンドからのレスポンスがある場合に呼び出されます(HTTPのステータスコードに関係なく)。
   101  	// バックエンドに到達できない場合は、オプションのErrorHandlerが呼び出され、ModifyResponseは呼び出されません。
   102  	//
   103  	// ModifyResponseがエラーを返す場合、それに対してErrorHandlerが呼び出されます。
   104  	// ErrorHandlerがnilの場合は、デフォルトの実装が使用されます。
   105  	ModifyResponse func(*http.Response) error
   106  
   107  	// ErrorHandlerは、バックエンドに到達したエラーやModifyResponseからのエラーを処理するオプションの関数です。
   108  	//
   109  	// nilの場合、デフォルトでは提供されたエラーをログに記録し、502 Status Bad Gatewayレスポンスを返します。
   110  	ErrorHandler func(http.ResponseWriter, *http.Request, error)
   111  }
   112  
   113  // BufferPoolは [io.CopyBuffer] で使用するための一時的なバイトスライスを取得および返却するためのインターフェースです。
   114  type BufferPool interface {
   115  	Get() []byte
   116  	Put([]byte)
   117  }
   118  
   119  // NewSingleHostReverseProxyは、URLを指定されたスキーム、ホスト、およびベースパスにルーティングする新しい [ReverseProxy] を返します。ターゲットのパスが"/base"であり、受信したリクエストが"/dir"である場合、ターゲットのリクエストは/base/dirになります。
   120  // NewSingleHostReverseProxyは、Hostヘッダーを書き換えません。
   121  //
   122  // NewSingleHostReverseProxyが提供する以上のカスタマイズをするには、Rewrite関数を使用して直接ReverseProxyを使用してください。ProxyRequest SetURLメソッドを使用してアウトバウンドリクエストをルーティングすることができます(ただし、SetURLはデフォルトでアウトバウンドリクエストのHostヘッダーを書き換えます)。
   123  //
   124  //	proxy := &ReverseProxy{
   125  //			Rewrite: func(r *ProxyRequest) {
   126  //				r.SetURL(target)
   127  //				r.Out.Host = r.In.Host // 必要に応じて
   128  //			},
   129  //		}
   130  func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
   131  
   132  func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)