Documentation
¶
Overview ¶
Package httputilは、net/httpパッケージにある一般的なものと補完するHTTPユーティリティ関数を提供します。
Index ¶
- Variables
- func DumpRequest(req *http.Request, body bool) ([]byte, error)
- func DumpRequestOut(req *http.Request, body bool) ([]byte, error)
- func DumpResponse(resp *http.Response, body bool) ([]byte, error)
- func NewChunkedReader(r io.Reader) io.Reader
- func NewChunkedWriter(w io.Writer) io.WriteCloser
- type BufferPool
- type ClientConndeprecated
- func (cc *ClientConn) Close() error
- func (cc *ClientConn) Do(req *http.Request) (*http.Response, error)
- func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader)
- func (cc *ClientConn) Pending() int
- func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error)
- func (cc *ClientConn) Write(req *http.Request) error
- type ProxyRequest
- type ReverseProxy
- type ServerConndeprecated
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Deprecated: 使用されていません。 ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"} // Deprecated: 使用されていません。 ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"} // Deprecated: 使用されていません。 ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"} )
var ErrLineTooLong = internal.ErrLineTooLong
ErrLineTooLong は、行が長すぎる不正なチャンクデータを読み取ると返されます。
Functions ¶
func DumpRequest ¶
DumpRequestは与えられたリクエストをHTTP/1.xのワイヤープレゼンテーションで返します。 クライアントのリクエストをデバッグするために、サーバーが使用するべきです。 返されるプレゼンテーションは近似値です。初期リクエストの一部の詳細は、http.Requestに解析される際に失われます。 特にヘッダーフィールド名の順序と大文字小文字の情報が失われます。複数の値を持つヘッダーの値の順序は保持されます。 HTTP/2のリクエストは、元のバイナリ表現ではなく、HTTP/1.xの形式でダンプされます。
bodyがtrueの場合、DumpRequestはbodyも返します。そのため、req.Bodyを消費し、同じバイトを返す新しいio.ReadCloserに置き換えます。 DumpRequestがエラーを返す場合、reqの状態は未定義です。
http.Request.Writeのドキュメントには、ダンプに含まれるreqのフィールドの詳細が記載されています。
Example ¶
package main import ( "github.com/shogo82148/std/fmt" "github.com/shogo82148/std/io" "github.com/shogo82148/std/log" "github.com/shogo82148/std/net/http" "github.com/shogo82148/std/net/http/httptest" "github.com/shogo82148/std/net/http/httputil" "github.com/shogo82148/std/strings" ) func main() { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { dump, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } fmt.Fprintf(w, "%q", dump) })) defer ts.Close() const body = "Go is a general-purpose language designed with systems programming in mind." req, err := http.NewRequest("POST", ts.URL, strings.NewReader(body)) if err != nil { log.Fatal(err) } req.Host = "www.example.org" resp, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() b, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s", b) }
Output: "POST / HTTP/1.1\r\nHost: www.example.org\r\nAccept-Encoding: gzip\r\nContent-Length: 75\r\nUser-Agent: Go-http-client/1.1\r\n\r\nGo is a general-purpose language designed with systems programming in mind."
func DumpRequestOut ¶
DumpRequestOutは、outgoingのクライアントリクエスト用のDumpRequestのようなものです。これには、標準のhttp.Transportが追加するUser-Agentなど、任意のヘッダーが含まれます。
Example ¶
package main import ( "github.com/shogo82148/std/fmt" "github.com/shogo82148/std/log" "github.com/shogo82148/std/net/http" "github.com/shogo82148/std/net/http/httputil" "github.com/shogo82148/std/strings" ) func main() { const body = "Go is a general-purpose language designed with systems programming in mind." req, err := http.NewRequest("PUT", "http://www.example.org", strings.NewReader(body)) if err != nil { log.Fatal(err) } dump, err := httputil.DumpRequestOut(req, true) if err != nil { log.Fatal(err) } fmt.Printf("%q", dump) }
Output: "PUT / HTTP/1.1\r\nHost: www.example.org\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 75\r\nAccept-Encoding: gzip\r\n\r\nGo is a general-purpose language designed with systems programming in mind."
func DumpResponse ¶
DumpResponseはDumpRequestと同様ですが、レスポンスをダンプします。
Example ¶
package main import ( "github.com/shogo82148/std/fmt" "github.com/shogo82148/std/log" "github.com/shogo82148/std/net/http" "github.com/shogo82148/std/net/http/httptest" "github.com/shogo82148/std/net/http/httputil" ) func main() { const body = "Go is a general-purpose language designed with systems programming in mind." ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Date", "Wed, 19 Jul 1972 19:00:00 GMT") fmt.Fprintln(w, body) })) defer ts.Close() resp, err := http.Get(ts.URL) if err != nil { log.Fatal(err) } defer resp.Body.Close() dump, err := httputil.DumpResponse(resp, true) if err != nil { log.Fatal(err) } fmt.Printf("%q", dump) }
Output: "HTTP/1.1 200 OK\r\nContent-Length: 76\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Wed, 19 Jul 1972 19:00:00 GMT\r\n\r\nGo is a general-purpose language designed with systems programming in mind.\n"
func NewChunkedReader ¶
NewChunkedReaderは、rから読み込まれたデータをHTTPの「チャンク」形式から変換して返す新しいchunkedReaderを返します。 chunkedReaderは、最後の長さ0のチャンクが読み込まれた時にio.EOFを返します。
NewChunkedReaderは通常のアプリケーションでは必要ありません。httpパッケージは、応答ボディを読み込む際に自動的にチャンクをデコードします。
func NewChunkedWriter ¶
func NewChunkedWriter(w io.Writer) io.WriteCloser
NewChunkedWriter は、w に書き込む前に書き込みを HTTP の "chunked" フォーマットに変換する新しい chunkedWriter を返します。返された chunkedWriter を閉じると、ストリームの終わりを示す最後の長さが 0 のチャンクが送信されますが、トレーラーの後に表示される最後の CRLF は送信されません。トレーラーと最後の CRLF は別個に書き込む必要があります。 NewChunkedWriter は通常のアプリケーションでは必要ありません。http パッケージは、ハンドラが Content-Length ヘッダーを設定しない場合、自動的にチャンキングを追加します。ハンドラ内で NewChunkedWriter を使用すると、二重チャンキングや Content-Length 長さでのチャンキングなど、間違った結果になります。
Types ¶
type BufferPool ¶ added in v1.6.0
BufferPoolはio.CopyBufferで使用するための一時的なバイトスライスを取得および返却するためのインターフェースです。
type ClientConn
deprecated
type ClientConn struct {
// contains filtered or unexported fields
}
ClientConnはGoの初期のHTTP実装の遺物です。 低レベルで古く、現在のGoのHTTPスタックでは使用されていません。 Go 1の前に削除すべきでした。
Deprecated: 代わりにpackage net/httpのClientまたはTransportを使用してください。
func NewClientConn ¶
func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn
NewClientConnはGoの初期のHTTP実装の遺産です。 これは低レベルで古く、現在のGoのHTTPスタックでは使用されていません。 Go 1より前に削除すべきでした。
廃止予定: 代わりにパッケージnet/httpのClientまたはTransportを使用してください。
func NewProxyClientConn ¶
func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn
NewProxyClientConn はGo言語の初期のHTTP実装の遺物です。 これは低レベルで古く、現在のGoのHTTPスタックでは使用されていません。 Go 1 より前に削除する必要があります。
廃止予定: 代わりに package net/http の Client または Transport を使用してください。
func (*ClientConn) Close ¶
func (cc *ClientConn) Close() error
Close calls Hijack and then also closes the underlying connection. CloseはHijackを呼び出し、その後下層の接続も閉じます。
func (*ClientConn) Hijack ¶
func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader)
HijackはClientConnを切り離し、基礎となる接続と読み込み側のbufioを返します。 また、左にデータが残っているかもしれない読み込み側のbufioも返します。 HijackはユーザーまたはReadがkeep-aliveロジックの終了をシグナルした前に呼び出すことができます。 ユーザーは、ReadまたはWriteが進行中の間にHijackを呼び出さないでください。
type ProxyRequest ¶ added in v1.20.0
type ProxyRequest struct { In *http.Request // Outはプロキシに送信されるリクエストです。 // Rewrite関数はこのリクエストを変更または置換する場合があります。 // Rewriteが呼び出される前に、ホップバイホップのヘッダーはこのリクエストから削除されます。 Out *http.Request }
ProxyRequestは、ReverseProxyによって書き換えられるリクエストを含んでいます。
func (*ProxyRequest) SetURL ¶ added in v1.20.0
func (r *ProxyRequest) SetURL(target *url.URL)
SetURLは、ターゲットに指定されたスキーム、ホスト、およびベースパスに従って、アウトバウンドリクエストをルーティングします。 もしターゲットのパスが"/base"であり、受信したリクエストが"/dir"である場合、ターゲットリクエストは"/base/dir"となります。
SetURLは、アウトバウンドのHostヘッダをターゲットのホストに合わせて書き換えます。 インバウンドのリクエストのHostヘッダを保持するために(NewSingleHostReverseProxyのデフォルトの動作):
rewriteFunc := func(r *httputil.ProxyRequest) { r.SetURL(url) r.Out.Host = r.In.Host }
func (*ProxyRequest) SetXForwarded ¶ added in v1.20.0
func (r *ProxyRequest) SetXForwarded()
SetXForwardedは、出力リクエストのX-Forwarded-For、X-Forwarded-Host、およびX-Forwarded-Protoヘッダーを設定します。
- X-Forwarded-Forヘッダーは、クライアントのIPアドレスに設定されます。 - X-Forwarded-Hostヘッダーは、クライアントが要求したホスト名に設定されます。 - X-Forwarded-Protoヘッダーは、入力リクエストがTLS対応の接続で行われたかどうかに応じて、「http」または「https」に設定されます。
出力リクエストに既存のX-Forwarded-Forヘッダーが含まれている場合、SetXForwardedはクライアントのIPアドレスを追加します。SetXForwardedを呼び出す前に、入力リクエストのX-Forwarded-Forヘッダー(Director関数を使用してReverseProxyを使用している場合のデフォルト動作)をコピーして、入力リクエストのX-Forwarded-Forヘッダーに追加します:
rewriteFunc := func(r *httputil.ProxyRequest) { r.Out.Header["X-Forwarded-For"] = r.In.Header["X-Forwarded-For"] r.SetXForwarded() }
type ReverseProxy ¶
type ReverseProxy struct { // Rewriteは、リクエストを変更してTransportを使用して送信される新しいリクエストに変換する関数でなければなりません。 // そのレスポンスは、元のクライアントに変更せずにコピーされます。 // Rewriteは、戻る後に提供されたProxyRequestまたはその内容にアクセスしてはいけません。 // // Forwarded、X-Forwarded、X-Forwarded-Host、およびX-Forwarded-Protoヘッダーは、 // Rewriteが呼び出される前に送信リクエストから削除されます。また、ProxyRequest.SetXForwardedメソッドも参照してください。 // // 解析できないクエリパラメータは、Rewriteが呼び出される前に送信リクエストから削除されます。 // Rewrite関数は、インバウンドURLのRawQueryをアウトバウンドURLにコピーして、元のパラメータ文字列を保持することがあります。 // 注意:これは、プロキシのクエリパラメータの解釈がダウンストリームサーバーと一致しない場合にセキュリティの問題を引き起こす可能性があります。 // // RewriteまたはDirectorのいずれか一つのみ設定できます。 Rewrite func(*ProxyRequest) // Director(ディレクター)は、リクエストを変更して新しいリクエストをTransport(トランスポート)を使用して送信します。そのレスポンスは、元のクライアントに変更せずにコピーされます。Directorは、戻った後に提供されたリクエストにアクセスしてはいけません。 // デフォルトでは、X-Forwarded-ForヘッダーはクライアントのIPアドレスの値に設定されます。もし既にX-Forwarded-Forヘッダーが存在する場合、クライアントのIPは既存の値に追加されます。ただし、特殊なケースとして、リクエストのRequest.Headerマップにヘッダーが存在しているが、値がnilである場合(Director関数によって設定された場合など)、X-Forwarded-Forヘッダーは変更されません。 // IPスプーフィングを防ぐために、クライアントまたは信頼できないプロキシから送られてきたプリエクスティングのX-Forwarded-Forヘッダーを削除するようにしてください。 // ディレクターが戻った後にリクエストからホップバイホップヘッダーが削除されます。これにより、ディレクターが追加したヘッダーも削除される可能性があります。リクエストの変更を保持するためには、リライト関数を使用してください。 // ディレクターが戻った後、リクエストのRequest.Formが設定されている場合は、解析できないクエリパラメータが送信先のリクエストから削除されます。 // RewriteまたはDirectorのうち、最大1つが設定できます。 Director func(*http.Request) // プロキシリクエストを実行するために使用されるトランスポートです。 // nil の場合、http.DefaultTransport が使用されます。 Transport http.RoundTripper // FlushIntervalは、レスポンスボディをクライアントにコピーする際のフラッシュ間隔を指定します。 // ゼロの場合、定期的なフラッシュは行われません。 // 負の値は、クライアントへの各書き込みの直後にすぐにフラッシュすることを意味します。 // FlushIntervalは、ReverseProxyがストリーミングレスポンスとしてレスポンスを認識するか、またはContentLengthが-1の場合は無視されます。 // このようなレスポンスの場合、書き込みはすぐにクライアントにフラッシュされます。 FlushInterval time.Duration // ErrorLogは、リクエストをプロキシする際に発生したエラーのオプションのロガーを指定します。 // nilの場合、ログはlogパッケージの標準ロガーを使用して行われます。 ErrorLog *log.Logger // BufferPoolは、io.CopyBufferがHTTPのレスポンスボディをコピーする際に使用するバイトスライスを取得するためのオプションのバッファプールを指定します。 BufferPool BufferPool // ModifyResponseはオプションの関数であり、バックエンドからのレスポンスを変更する役割を持ちます。 // この関数は、バックエンドからのレスポンスがある場合に呼び出されます(HTTPのステータスコードに関係なく)。 // バックエンドに到達できない場合は、オプションのErrorHandlerが呼び出され、ModifyResponseは呼び出されません。 // // ModifyResponseがエラーを返す場合、それに対してErrorHandlerが呼び出されます。 // ErrorHandlerがnilの場合は、デフォルトの実装が使用されます。 ModifyResponse func(*http.Response) error // ErrorHandlerは、バックエンドに到達したエラーやModifyResponseからのエラーを処理するオプションの関数です。 // // nilの場合、デフォルトでは提供されたエラーをログに記録し、502 Status Bad Gatewayレスポンスを返します。 ErrorHandler func(http.ResponseWriter, *http.Request, error) }
ReverseProxyは、受信したリクエストを別のサーバーに送信し、レスポンスをクライアントにプロキシするHTTPハンドラです。
もし基礎となるトランスポートがClientTrace.Got1xxResponseをサポートしている場合、1xxのレスポンスはクライアントに転送されます。
Example ¶
package main import ( "github.com/shogo82148/std/fmt" "github.com/shogo82148/std/io" "github.com/shogo82148/std/log" "github.com/shogo82148/std/net/http" "github.com/shogo82148/std/net/http/httptest" "github.com/shogo82148/std/net/http/httputil" "github.com/shogo82148/std/net/url" ) func main() { backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "this call was relayed by the reverse proxy") })) defer backendServer.Close() rpURL, err := url.Parse(backendServer.URL) if err != nil { log.Fatal(err) } frontendProxy := httptest.NewServer(&httputil.ReverseProxy{ Rewrite: func(r *httputil.ProxyRequest) { r.SetXForwarded() r.SetURL(rpURL) }, }) defer frontendProxy.Close() resp, err := http.Get(frontendProxy.URL) if err != nil { log.Fatal(err) } b, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s", b) }
Output: this call was relayed by the reverse proxy
func NewSingleHostReverseProxy ¶
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy
NewSingleHostReverseProxyは、URLを指定されたスキーム、ホスト、およびベースパスにルーティングする新しいReverseProxyを返します。ターゲットのパスが"/base"であり、受信したリクエストが"/dir"である場合、ターゲットのリクエストは/base/dirになります。 NewSingleHostReverseProxyは、Hostヘッダーを書き換えません。 NewSingleHostReverseProxyが提供する以上のカスタマイズをするには、Rewrite関数を使用して直接ReverseProxyを使用してください。ProxyRequest SetURLメソッドを使用してアウトバウンドリクエストをルーティングすることができます(ただし、SetURLはデフォルトでアウトバウンドリクエストのHostヘッダーを書き換えます)。
proxy := &ReverseProxy{ Rewrite: func(r *ProxyRequest) { r.SetURL(target) r.Out.Host = r.In.Host // 必要に応じて }, }
func (*ReverseProxy) ServeHTTP ¶
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)
type ServerConn
deprecated
type ServerConn struct {
// contains filtered or unexported fields
}
ServerConnはGoの初期のHTTP実装の遺物です。 それは低レベルで古く、Goの現在のHTTPスタックでは使用されていません。 Go 1よりも前に削除すべきでした。
Deprecated: 代わりにnet/httpパッケージのServerを使用してください。
func NewServerConn
deprecated
func NewServerConn(c net.Conn, r *bufio.Reader) *ServerConn
NewServerConnはGoの初期のHTTP実装の遺物です。 これは低レベルで古いものであり、現行のGoのHTTPスタックでは使用されていません。 Go 1より前に削除すべきでした。
Deprecated: 代わりに package net/http のServerを使用してください。
func (*ServerConn) Hijack ¶
func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader)
HijackはServerConnを切り離し、基礎となる接続と、残っているデータを持つ読み込み側のbufioを返します。 HijackはReadがkeep-aliveロジックの終了を示すまえに呼び出される可能性があります。ユーザーはReadやWriteが進行中の間にHijackを呼び出すべきではありません。