httputil

package
v1.21.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2023 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package httputilは、net/httpパッケージにある一般的なものと補完するHTTPユーティリティ関数を提供します。

Index

Examples

Constants

This section is empty.

Variables

View Source
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"}
)
View Source
var ErrLineTooLong = internal.ErrLineTooLong

ErrLineTooLong は、行が長すぎる不正なチャンクデータを読み取ると返されます。

Functions

func DumpRequest

func DumpRequest(req *http.Request, body bool) ([]byte, error)

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

func DumpRequestOut(req *http.Request, body bool) ([]byte, error)

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

func DumpResponse(resp *http.Response, body bool) ([]byte, error)

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

func NewChunkedReader(r io.Reader) io.Reader

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

type BufferPool interface {
	Get() []byte
	Put([]byte)
}

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) Do

func (cc *ClientConn) Do(req *http.Request) (*http.Response, error)

Doはリクエストを書き込み、レスポンスを読み取る便利なメソッドです。

func (*ClientConn) Hijack

func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader)

HijackはClientConnを切り離し、基礎となる接続と読み込み側のbufioを返します。 また、左にデータが残っているかもしれない読み込み側のbufioも返します。 HijackはユーザーまたはReadがkeep-aliveロジックの終了をシグナルした前に呼び出すことができます。 ユーザーは、ReadまたはWriteが進行中の間にHijackを呼び出さないでください。

func (*ClientConn) Pending

func (cc *ClientConn) Pending() int

Pendingは、接続に送信された未応答のリクエストの数を返します。

func (*ClientConn) Read

func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error)

Readはワイヤから次のレスポンスを読み込みます。有効なレスポンスはErrPersistEOFと一緒に返される場合があります。これはリモートがこれがサービスされる最後のリクエストであることを要求したことを意味します。ReadはWriteと同時に呼び出すことができますが、他のReadと同時には呼び出すことはできません。

func (*ClientConn) Write

func (cc *ClientConn) Write(req *http.Request) error

Writeはリクエストを書き込みます。もしHTTP keep-aliveによって接続が閉じられた場合、ErrPersistEOFエラーが返されます。もしreq.Closeがtrueの場合、このリクエストの後にkeep-alive接続が論理的に閉じられ、対向サーバーに通知されます。ErrUnexpectedEOFは、リモートが基礎となるTCP接続を閉じたことを示しており、通常は正常な終了と見なされます。

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) Close

func (sc *ServerConn) Close() error

Closeによってヒジャックされ、その後基礎となる接続も閉じます。

func (*ServerConn) Hijack

func (sc *ServerConn) Hijack() (net.Conn, *bufio.Reader)

HijackはServerConnを切り離し、基礎となる接続と、残っているデータを持つ読み込み側のbufioを返します。 HijackはReadがkeep-aliveロジックの終了を示すまえに呼び出される可能性があります。ユーザーはReadやWriteが進行中の間にHijackを呼び出すべきではありません。

func (*ServerConn) Pending

func (sc *ServerConn) Pending() int

Pendingは、接続されたリクエストの未回答数を返します。

func (*ServerConn) Read

func (sc *ServerConn) Read() (*http.Request, error)

Readはワイヤ上の次のリクエストを返します。ErrPersistEOFは、優雅にもうリクエストがないことが確定した場合に返されます(例えば、HTTP/1.0接続の最初のリクエスト後、またはHTTP/1.1接続のConnection: close後など)。

func (*ServerConn) Write

func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error

Writeはreqに応じたrespを書き込みます。接続を正常に終了させるためには、 Response.Closeフィールドをtrueに設定してください。Writeは、Read側で返される すべてのエラーに関係なく、エラーが返されるまで操作可能であると見なされるべきです。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL