github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/net/http/transport.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 client implementation. See RFC 7230 through 7235.
     6  //
     7  // This is the low-level Transport implementation of RoundTripper.
     8  // The high-level interface is in client.go.
     9  
    10  package http
    11  
    12  import (
    13  	"github.com/shogo82148/std/context"
    14  	"github.com/shogo82148/std/crypto/tls"
    15  	"github.com/shogo82148/std/errors"
    16  	"github.com/shogo82148/std/io"
    17  	"github.com/shogo82148/std/net"
    18  	"github.com/shogo82148/std/net/url"
    19  	"github.com/shogo82148/std/sync"
    20  	"github.com/shogo82148/std/sync/atomic"
    21  	"github.com/shogo82148/std/time"
    22  )
    23  
    24  // DefaultTransportは [Transport] のデフォルト実装であり、[DefaultClient] によって使用されます。
    25  // 必要に応じてネットワーク接続を確立し、後続の呼び出しで再利用するためにキャッシュします。
    26  // 環境変数HTTP_PROXY、HTTPS_PROXY、およびNO_PROXY(またはその小文字バージョン)によって指示されたように、HTTPプロキシを使用します。
    27  var DefaultTransport RoundTripper = &Transport{
    28  	Proxy: ProxyFromEnvironment,
    29  	DialContext: defaultTransportDialContext(&net.Dialer{
    30  		Timeout:   30 * time.Second,
    31  		KeepAlive: 30 * time.Second,
    32  	}),
    33  	ForceAttemptHTTP2:     true,
    34  	MaxIdleConns:          100,
    35  	IdleConnTimeout:       90 * time.Second,
    36  	TLSHandshakeTimeout:   10 * time.Second,
    37  	ExpectContinueTimeout: 1 * time.Second,
    38  }
    39  
    40  // DefaultMaxIdleConnsPerHostは、[Transport] のMaxIdleConnsPerHostのデフォルト値です。
    41  const DefaultMaxIdleConnsPerHost = 2
    42  
    43  // Transportは、HTTP、HTTPS、およびHTTPプロキシ(HTTPまたはHTTPS with CONNECTのいずれか)をサポートする [RoundTripper] の実装です。
    44  //
    45  // デフォルトでは、Transportは将来の再利用のために接続をキャッシュします。
    46  // これにより、多くのホストにアクセスする場合に多数のオープンな接続が残る可能性があります。
    47  // この動作は、[Transport.CloseIdleConnections] メソッドと [Transport.MaxIdleConnsPerHost] および [Transport.DisableKeepAlives] フィールドを使用して管理できます。
    48  //
    49  // Transportは必要に応じて作成するのではなく、再利用する必要があります。
    50  // Transportは、複数のgoroutineによる同時使用に対して安全です。
    51  //
    52  // Transportは、HTTPおよびHTTPSリクエストを行うための低レベルのプリミティブです。
    53  // クッキーやリダイレクトなどの高レベルの機能については、[Client] を参照してください。
    54  //
    55  // Transportは、HTTP URLではHTTP/1.1を、HTTPS URLではHTTP/1.1またはHTTP/2を使用します。
    56  // これは、サーバーがHTTP/2をサポートしているかどうか、およびTransportの構成によって異なります。
    57  // [DefaultTransport] はHTTP/2をサポートしています。
    58  // Transportで明示的にHTTP/2を有効にするには、golang.org/x/net/http2 を使用してConfigureTransportを呼び出します。
    59  // HTTP/2についての詳細については、パッケージのドキュメントを参照してください。
    60  //
    61  // ステータスコードが1xx範囲にあるレスポンスは、自動的に処理されます(100 expect-continue)。
    62  // ただし、HTTPステータスコード101(Switching Protocols)は、終端ステータスと見なされ、[Transport.RoundTrip] によって返されます。
    63  // 無視された1xxレスポンスを表示するには、httptraceトレースパッケージのClientTrace.Got1xxResponseを使用します。
    64  //
    65  // Transportは、ネットワークエラーに遭遇した場合にのみ、接続がすでに正常に使用されており、
    66  // リクエストが冪等であり、ボディがないか、または [Request.GetBody] が定義されている場合に、
    67  // リクエストを再試行します。HTTPリクエストは、HTTPメソッドがGET、HEAD、OPTIONS、またはTRACEである場合、
    68  // または [Header] マップに「Idempotency-Key」または「X-Idempotency-Key」エントリが含まれている場合、冪等と見なされます。
    69  // 冪等性キーの値がゼロ長のスライスの場合、リクエストは冪等と見なされますが、ヘッダーはワイヤーに送信されません。
    70  type Transport struct {
    71  	idleMu       sync.Mutex
    72  	closeIdle    bool
    73  	idleConn     map[connectMethodKey][]*persistConn
    74  	idleConnWait map[connectMethodKey]wantConnQueue
    75  	idleLRU      connLRU
    76  
    77  	reqMu       sync.Mutex
    78  	reqCanceler map[cancelKey]func(error)
    79  
    80  	altMu    sync.Mutex
    81  	altProto atomic.Value
    82  
    83  	connsPerHostMu   sync.Mutex
    84  	connsPerHost     map[connectMethodKey]int
    85  	connsPerHostWait map[connectMethodKey]wantConnQueue
    86  
    87  	// Proxyは、指定されたRequestに対するプロキシを返す関数を指定します。
    88  	// 関数が非nilのエラーを返す場合、リクエストは提供されたエラーで中止されます。
    89  	//
    90  	// プロキシのタイプは、URLスキームによって決定されます。
    91  	// "http"、"https"、"sock5"、および"socks5h"がサポートされています。
    92  	// スキームが空の場合、"http"が想定されます。
    93  	// "socks5"は"socks5h"と同じように扱われます。
    94  	//
    95  	// プロキシURLにuserinfoサブコンポーネントが含まれている場合、
    96  	// プロキシリクエストはProxy-Authorizationヘッダーでユーザー名とパスワードを渡します。
    97  	//
    98  	// Proxyがnilまたはnilの*URLを返す場合、プロキシは使用されません。
    99  	Proxy func(*Request) (*url.URL, error)
   100  
   101  	// OnProxyConnectResponseは、TransportがCONNECTリクエストのプロキシからHTTPレスポンスを受信したときに呼び出されます。
   102  	// これは、200 OKレスポンスのチェックの前に呼び出されます。
   103  	// エラーを返すと、リクエストはそのエラーで失敗します。
   104  	OnProxyConnectResponse func(ctx context.Context, proxyURL *url.URL, connectReq *Request, connectRes *Response) error
   105  
   106  	// DialContextは、暗号化されていないTCP接続を作成するためのダイアル関数を指定します。
   107  	// DialContextがnilである場合(および下記の非推奨のDialもnilである場合)、
   108  	// トランスポートはnetパッケージを使用してダイアルします。
   109  	//
   110  	// DialContextは、RoundTripの呼び出しと並行して実行されます。
   111  	// ダイアルを開始するRoundTrip呼び出しが、後のDialContextが完了する前に
   112  	// 以前にダイアルされた接続を使用する場合があります。
   113  	DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
   114  
   115  	// Dialは、暗号化されていないTCP接続を作成するためのダイアル関数を指定します。
   116  	//
   117  	// Dialは、RoundTripの呼び出しと並行して実行されます。
   118  	// 以前にダイアルされた接続が後でアイドル状態になる場合、
   119  	// 後のDialが完了する前に、ダイアルを開始するRoundTrip呼び出しが以前にダイアルされた接続を使用する場合があります。
   120  	//
   121  	// Deprecated: 代わりにDialContextを使用してください。これにより、トランスポートはダイアルが不要になった直後にキャンセルできます。
   122  	// 両方が設定されている場合、DialContextが優先されます。
   123  	Dial func(network, addr string) (net.Conn, error)
   124  
   125  	// DialTLSContextは、プロキシを使用しないHTTPSリクエストのためのTLS接続を作成するためのオプションのダイアル関数を指定します。
   126  	//
   127  	// DialTLSContextがnilである場合(および下記の非推奨のDialTLSもnilである場合)、
   128  	// DialContextとTLSClientConfigが使用されます。
   129  	//
   130  	// DialTLSContextが設定されている場合、HTTPSリクエストに対してDialおよびDialContextフックは使用されず、
   131  	// TLSClientConfigおよびTLSHandshakeTimeoutは無視されます。
   132  	// 返されたnet.Connは、すでにTLSハンドシェイクを完了しているものと見なされます。
   133  	DialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
   134  
   135  	// DialTLSは、プロキシを使用しないHTTPSリクエストのためのTLS接続を作成するためのオプションのダイアル関数を指定します。
   136  	//
   137  	// Deprecated: 代わりにDialTLSContextを使用してください。これにより、トランスポートはダイアルが不要になった直後にキャンセルできます。
   138  	// 両方が設定されている場合、DialTLSContextが優先されます。
   139  	DialTLS func(network, addr string) (net.Conn, error)
   140  
   141  	// TLSClientConfigは、tls.Clientで使用するTLS構成を指定します。
   142  	// nilの場合、デフォルトの構成が使用されます。
   143  	// nil以外の場合、HTTP/2サポートがデフォルトで有効になっていない場合があります。
   144  	TLSClientConfig *tls.Config
   145  
   146  	// TLSHandshakeTimeoutは、TLSハンドシェイクを待機する最大時間を指定します。
   147  	// ゼロの場合、タイムアウトはありません。
   148  	TLSHandshakeTimeout time.Duration
   149  
   150  	// DisableKeepAlivesがtrueの場合、HTTP keep-alivesが無効になり、
   151  	// サーバーへの接続は単一のHTTPリクエストにのみ使用されます。
   152  	//
   153  	// これは、同様に名前が付けられたTCP keep-alivesとは無関係です。
   154  	DisableKeepAlives bool
   155  
   156  	// DisableCompressionがtrueの場合、Transportは、Requestに既存のAccept-Encoding値がない場合に、
   157  	// "Accept-Encoding: gzip"リクエストヘッダーで圧縮を要求しません。
   158  	// Transportが自動的にgzipを要求し、gzipされたレスポンスを受け取った場合、Response.Bodyで透過的にデコードされます。
   159  	// ただし、ユーザーが明示的にgzipを要求した場合は、自動的に解凍されません。
   160  	DisableCompression bool
   161  
   162  	// MaxIdleConnsは、すべてのホストをまたいでアイドル(keep-alive)接続の最大数を制御します。
   163  	// ゼロの場合、制限はありません。
   164  	MaxIdleConns int
   165  
   166  	// MaxIdleConnsPerHostがゼロでない場合、ホストごとに保持する最大アイドル(keep-alive)接続数を制御します。
   167  	// ゼロの場合、DefaultMaxIdleConnsPerHostが使用されます。
   168  	MaxIdleConnsPerHost int
   169  
   170  	// MaxConnsPerHostは、ダイアル、アクティブ、およびアイドル状態の接続を含む、ホストごとの総接続数をオプションで制限します。
   171  	// 制限を超えると、ダイアルはブロックされます。
   172  	//
   173  	// ゼロは制限がないことを意味します。
   174  	MaxConnsPerHost int
   175  
   176  	// IdleConnTimeoutは、アイドル(keep-alive)接続が自己クローズする前にアイドル状態になる最大時間です。
   177  	// ゼロは制限がないことを意味します。
   178  	IdleConnTimeout time.Duration
   179  
   180  	// ResponseHeaderTimeoutがゼロでない場合、リクエスト(ボディがある場合はそれも含む)を完全に書き込んだ後、
   181  	// サーバーのレスポンスヘッダーを待機する時間を指定します。
   182  	// この時間には、レスポンスボディを読み取る時間は含まれません。
   183  	ResponseHeaderTimeout time.Duration
   184  
   185  	// ExpectContinueTimeoutがゼロでない場合、リクエストに"Expect: 100-continue"ヘッダーがある場合、
   186  	// リクエストヘッダーを完全に書き込んだ後、サーバーの最初のレスポンスヘッダーを待機する時間を指定します。
   187  	// ゼロはタイムアウトがないことを意味し、サーバーの承認を待たずに、すぐにボディを送信します。
   188  	// この時間には、リクエストヘッダーを送信する時間は含まれません。
   189  	ExpectContinueTimeout time.Duration
   190  
   191  	// TLSNextProtoは、TLS ALPNプロトコルネゴシエーション後にTransportが代替プロトコル(HTTP/2など)に切り替える方法を指定します。
   192  	// Transportがプロトコル名が空でないTLS接続をダイアルし、TLSNextProtoにそのキーのマップエントリが含まれている場合("h2"など)、
   193  	// リクエストの権限("example.com"または"example.com:1234"など)とTLS接続でfuncが呼び出されます。
   194  	// この関数は、その後リクエストを処理するRoundTripperを返さなければなりません。
   195  	// TLSNextProtoがnilでない場合、HTTP/2サポートは自動的に有効になりません。
   196  	TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
   197  
   198  	// ProxyConnectHeaderは、CONNECTリクエスト中にプロキシに送信するヘッダーをオプションで指定します。
   199  	// ヘッダーを動的に設定するには、GetProxyConnectHeaderを参照してください。
   200  	ProxyConnectHeader Header
   201  
   202  	// GetProxyConnectHeaderは、ip:portターゲットへのCONNECTリクエスト中にproxyURLに送信するヘッダーを返すためのオプションの関数を指定します。
   203  	// エラーを返すと、TransportのRoundTripはそのエラーで失敗します。
   204  	// ヘッダーを追加しない場合は、(nil, nil)を返すことができます。
   205  	// GetProxyConnectHeaderが非nilの場合、ProxyConnectHeaderは無視されます。
   206  	GetProxyConnectHeader func(ctx context.Context, proxyURL *url.URL, target string) (Header, error)
   207  
   208  	// MaxResponseHeaderBytesは、サーバーのレスポンスヘッダーに許可されるレスポンスバイト数の制限を指定します。
   209  	//
   210  	// ゼロは、デフォルトの制限を使用することを意味します。
   211  	MaxResponseHeaderBytes int64
   212  
   213  	// WriteBufferSizeは、トランスポートへの書き込み時に使用される書き込みバッファのサイズを指定します。
   214  	// ゼロの場合、デフォルト値(現在は4KB)が使用されます。
   215  	WriteBufferSize int
   216  
   217  	// ReadBufferSizeは、トランスポートから読み取るときに使用される読み取りバッファのサイズを指定します。
   218  	// ゼロの場合、デフォルト値(現在は4KB)が使用されます。
   219  	ReadBufferSize int
   220  
   221  	// nextProtoOnce guards initialization of TLSNextProto and
   222  	// h2transport (via onceSetNextProtoDefaults)
   223  	nextProtoOnce      sync.Once
   224  	h2transport        h2Transport
   225  	tlsNextProtoWasNil bool
   226  
   227  	// ForceAttemptHTTP2は、非ゼロの
   228  	// Dial, DialTLS, または DialContext 関数または TLSClientConfig が提供されたときに、
   229  	// HTTP/2が有効になるかどうかを制御します。
   230  	// デフォルトでは、これらのフィールドのいずれかの使用は、保守的にHTTP/2を無効にします。
   231  	// カスタムダイヤラーやTLS設定を使用しつつ、HTTP/2への
   232  	// アップグレードを試みるには、これをtrueに設定します。
   233  	ForceAttemptHTTP2 bool
   234  }
   235  
   236  // Cloneは、tのエクスポートされたフィールドのディープコピーを返します。
   237  func (t *Transport) Clone() *Transport
   238  
   239  // ProxyFromEnvironmentは、環境変数HTTP_PROXY、HTTPS_PROXY、およびNO_PROXY(またはそれらの小文字バージョン)によって示されるように、
   240  // 指定されたリクエストに使用するプロキシのURLを返します。
   241  // リクエストは、NO_PROXYによって除外されていない限り、スキームに一致する環境変数からプロキシを使用します。
   242  //
   243  // 環境値は、完全なURLまたは"host[:port]"のいずれかである場合があります。この場合、"http"スキームが想定されます。
   244  // 値が異なる形式の場合は、エラーが返されます。
   245  //
   246  // 環境変数でプロキシが定義されていない場合、またはNO_PROXYによって指定されたリクエストにプロキシを使用しない場合、
   247  // nilのURLとnilのエラーが返されます。
   248  //
   249  // 特別な場合として、req.URL.Hostが"localhost"(ポート番号ありまたはなし)の場合、nilのURLとnilのエラーが返されます。
   250  func ProxyFromEnvironment(req *Request) (*url.URL, error)
   251  
   252  // ProxyURLは、常に同じURLを返すプロキシ関数([Transport] で使用するため)を返します。
   253  func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, error)
   254  
   255  // ErrSkipAltProtocolは、Transport.RegisterProtocolによって定義されたセンチネルエラー値です。
   256  var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
   257  
   258  // RegisterProtocolは、新しいプロトコルをスキームとともに登録します。
   259  // [Transport] は、指定されたスキームを使用してリクエストをrtに渡します。
   260  // HTTPリクエストのセマンティクスをシミュレートする責任は、rtにあります。
   261  //
   262  // RegisterProtocolは、他のパッケージが"ftp"や"file"などのプロトコルスキームの実装を提供するために使用できます。
   263  //
   264  // rt.RoundTripが [ErrSkipAltProtocol] を返す場合、Transportは、
   265  // 登録されたプロトコルのように扱わずに、その1つのリクエストに対して自身で [Transport.RoundTrip] を処理します。
   266  func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper)
   267  
   268  // CloseIdleConnectionsは、以前のリクエストから接続されていたが、現在はアイドル状態になっている"keep-alive"状態の接続を閉じます。
   269  // 現在使用中の接続は中断しません。
   270  func (t *Transport) CloseIdleConnections()
   271  
   272  // CancelRequestは、その接続を閉じることにより、進行中のリクエストをキャンセルします。
   273  // CancelRequestは、 [Transport.RoundTrip] が返された後にのみ呼び出す必要があります。
   274  //
   275  // Deprecated: 代わりに、キャンセル可能なコンテキストを持つリクエストを作成するために [Request.WithContext] を使用してください。
   276  // CancelRequestは、HTTP/2リクエストをキャンセルできません。
   277  func (t *Transport) CancelRequest(req *Request)
   278  
   279  var _ io.ReaderFrom = (*persistConnWriter)(nil)