reverseproxy

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2024 License: Apache-2.0 Imports: 25 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BaseTransport http.RoundTripper = &http.Transport{
	Proxy: func(req *http.Request) (*url.URL, error) {
		hosts := strings.Split(os.Getenv("FORWARD_PROXY_HOSTS"), ",")
		for _, host := range hosts {
			if req.Host == host || req.URL.Host == host {
				return ProxyConfig.ProxyFunc()(req.URL)
			}
		}
		return http.ProxyFromEnvironment(req)
	},
	DialContext: (&net.Dialer{
		Timeout:   60 * time.Second,
		KeepAlive: 60 * time.Second,
	}).DialContext,
	TLSHandshakeTimeout:   10 * time.Second,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
	ForceAttemptHTTP2:     true,
}

BaseTransport 返回一个基础的 http.RoundTripper. 它检查 *http.Request 所请求的 host 是否在 FORWARD_PROXY_HOSTS 清单内, 如果在清单内, 则使用 ProxyConfig 的代理配置, 如不在清单内, 则使用默认的代理配置 http.ProxyFromEnvironment.

View Source
var (
	DefaultBufferPool = NewBufferPool(1024 * 3)
)
View Source
var ProxyConfig = &httpproxy.Config{
	HTTPProxy:  os.Getenv("FORWARD_HTTP_PROXY"),
	HTTPSProxy: os.Getenv("FORWARD_HTTPS_PROXY"),
	NoProxy:    os.Getenv("NO_PROXY"),
	CGI:        os.Getenv("REQUEST_METHOD") != "",
}

ProxyConfig 是正向代理配置, 即 transport 出口流量的代理配置

Functions

func AppendDirectors

func AppendDirectors(ctx context.Context, director ...func(r *http.Request))

func DoNothingDirector

func DoNothingDirector(_ *http.Request)

func EqualFold

func EqualFold(s, t string) bool

EqualFold is strings.EqualFold, ASCII only. It reports whether s and t are equal, ASCII-case-insensitively.

func GenCurl

func GenCurl(infor HttpInfor) string

func IsPrint

func IsPrint(s string) bool

IsPrint returns whether s is ASCII and printable according to https://tools.ietf.org/html/rfc20#section-4.2.

func NewBufferPool

func NewBufferPool[IntegerType ~int | ~int8 | ~int16 | ~int32 | ~int64 |
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64](size IntegerType) httputil.BufferPool

func RegisterFilterCreator

func RegisterFilterCreator(name string, creator FilterCreator)

Types

type ActualRequestFilter

type ActualRequestFilter interface {
	OnActualRequest(ctx context.Context, infor HttpInfor)
}

type BufferPool

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

A BufferPool is an interface for getting and returning temporary byte slices for use by io.CopyBuffer.

type CtxKeyHandleFuncForActualRequest

type CtxKeyHandleFuncForActualRequest struct{ CtxKeyHandleFuncForActualRequest any }

type CtxKeyMap

type CtxKeyMap struct{ CtxKeyMap any }

type CtxKeyPath

type CtxKeyPath struct{ CtxKeyPath any }

type CtxKeyPathMatcher

type CtxKeyPathMatcher struct{ CtxKeyPathVars any }

type CurlPrinterTransport

type CurlPrinterTransport struct {
	Logger logs.Logger
	Inner  http.RoundTripper
}

func (*CurlPrinterTransport) RoundTrip

func (t *CurlPrinterTransport) RoundTrip(req *http.Request) (*http.Response, error)

type DefaultResponseFilter

type DefaultResponseFilter struct {
	*bytes.Buffer
}

DefaultResponseFilter 的 OnResponseChunk 和 OnResponseEOF 将每一片 chunk 记录在自身的 buffer 中, 没有做其他任何事情.

func NewDefaultResponseFilter

func NewDefaultResponseFilter() *DefaultResponseFilter

func (*DefaultResponseFilter) OnResponseChunk

func (d *DefaultResponseFilter) OnResponseChunk(ctx context.Context, _ HttpInfor, w Writer, chunk []byte) (signal Signal, err error)

OnResponseChunk 将传入的 chunk 记录在自身的 buffer 中, 同时通过写入 w io.Writer 的方式传递给下一个 ResponseFilter, 没有做其他任何事情.

func (*DefaultResponseFilter) OnResponseChunkImmutable

func (d *DefaultResponseFilter) OnResponseChunkImmutable(ctx context.Context, _ HttpInfor, copiedChunk []byte) (signal Signal, err error)

func (*DefaultResponseFilter) OnResponseEOF

func (d *DefaultResponseFilter) OnResponseEOF(ctx context.Context, _ HttpInfor, w Writer, chunk []byte) (err error)

OnResponseEOF 将传入的 chunk 记录在自身的 buffer 中, 同时通过写入 w io.Writer 的方式传递给下一个 ResponseFilter, 没有做其他任何事情.

func (*DefaultResponseFilter) OnResponseEOFImmutable

func (d *DefaultResponseFilter) OnResponseEOFImmutable(ctx context.Context, _ HttpInfor, copiedChunk []byte) (err error)

type DoNothingTransport

type DoNothingTransport struct {
	Response *http.Response
}

func (*DoNothingTransport) RoundTrip

func (d *DoNothingTransport) RoundTrip(req *http.Request) (*http.Response, error)

type Enable

type Enable interface {
	Enable(context.Context, *http.Request) bool
}

type Filter

type Filter any

type FilterConfig

type FilterConfig struct {
	Name   string          `json:"name" yaml:"name"`
	Config json.RawMessage `json:"config" yaml:"config"`
}

type FilterCreator

type FilterCreator func(json.RawMessage) (Filter, error)

func GetFilterCreator

func GetFilterCreator(name string) (FilterCreator, bool)

func MustGetFilterCreator

func MustGetFilterCreator(name string) FilterCreator

type HttpInfor

type HttpInfor interface {
	Method() string
	URL() *url.URL
	Status() string
	StatusCode() int
	Header() http.Header
	Cookie(string) (*http.Cookie, error)
	ContentLength() int64
	Host() string
	RemoteAddr() string
	// Body only for getting request body and only on request stage.
	Body() io.ReadCloser
	SetBody(body io.ReadCloser, size int64)
	SetBody2(body interface{})
	// BodyBuffer only for getting request body and only on request stage.
	BodyBuffer(all ...bool) *bytes.Buffer
	// Request only on request stage.
	Request() *http.Request
}

func NewInfor

func NewInfor[R httputil.RequestResponse](ctx context.Context, r R) HttpInfor

type ImmutableResponseFilter

type ImmutableResponseFilter interface {
	// OnResponseChunkImmutable 对比 OnResponseChunk,不传入 w Writer,且传入的是 chunk 的拷贝,
	// 因此对后续 filter 无影响,只是用于读取 chunk 数据并处理
	OnResponseChunkImmutable(ctx context.Context, infor HttpInfor, copiedChunk []byte) (signal Signal, err error)
	// OnResponseEOFImmutable 对比 OnResponseEOF,不传入 w Writer,且传入的是 chunk 的拷贝,
	// 因此对后续 filter 无影响,只是用于读取 chunk 数据并处理
	OnResponseEOFImmutable(ctx context.Context, infor HttpInfor, copiedChunk []byte) error
}

type LoggerCtxKey

type LoggerCtxKey struct{ LoggerCtxKey any }

type MapKeyDirectors

type MapKeyDirectors struct{ CtxKeyDirectors any }

type MultiByteWriter

type MultiByteWriter struct {
	// contains filtered or unexported fields
}

func NewMultiByteWriter

func NewMultiByteWriter(writers ...io.Writer) *MultiByteWriter

func (*MultiByteWriter) Write

func (mbw *MultiByteWriter) Write(p []byte) (n int, err error)

func (*MultiByteWriter) WriteByte

func (mbw *MultiByteWriter) WriteByte(c byte) error

type MultiResponseWriter

type MultiResponseWriter interface {
	MultiResponseWriter(ctx context.Context) []io.ReadWriter
}

type MutexCtxKey

type MutexCtxKey struct{ MutexCtxKey any }

type NamingFilter

type NamingFilter struct {
	Name   string
	Filter Filter
}

type OriginalRequestFilter

type OriginalRequestFilter interface {
	OnOriginalRequest(ctx context.Context, infor HttpInfor)
}

type RequestFilter

type RequestFilter interface {
	OnRequest(ctx context.Context, w http.ResponseWriter, infor HttpInfor) (signal Signal, err error)
}

type ResponseFilter

type ResponseFilter interface {
	// OnResponseChunk 每被调用一次, 传入一个 response chunk, ResponseFilter 的实现者需要自行决定如何处理这些 chunk.
	// 对大多数情况来说, 实现者可以将这些 chunk 缓存到 filter 实例中, 待 response chunks 全部传完后整体处理.
	// 注意: w Writer 是将 response chunk 传入下一个 ResponseFilter 的句柄, 要将处理后的数据按需写入这个 Writer,
	// 不然后续的 ResponseFilter 都会丢失这部分数据.
	OnResponseChunk(ctx context.Context, infor HttpInfor, w Writer, chunk []byte) (signal Signal, err error)

	// OnResponseEOF 当 OnResponseEOF 被调用时, 表示这是最后一次传入 response chunk, OnResponseEOF 应当做一些收尾工作.
	// 比如 OnResponseChunk 截留了的数据, 可以在此时写入 w Writer.
	OnResponseEOF(ctx context.Context, infor HttpInfor, w Writer, chunk []byte) error

	ImmutableResponseFilter
}

type ReverseProxy

type ReverseProxy struct {
	// Director must be a function which modifies
	// the request into a new request to be sent
	// using Transport. Its response is then copied
	// back to the original client unmodified.
	// Director must not access the provided Request
	// after returning.
	Director func(*http.Request)

	// The transport used to perform proxy requests.
	// If nil, http.DefaultTransport is used.
	Transport http.RoundTripper

	// FlushInterval specifies the flush interval
	// to flush to the client while copying the
	// response body.
	// If zero, no periodic flushing is done.
	// A negative value means to flush immediately
	// after each write to the client.
	// The FlushInterval is ignored when ReverseProxy
	// recognizes a response as a streaming response, or
	// if its ContentLength is -1; for such responses, writes
	// are flushed to the client immediately.
	FlushInterval time.Duration

	// ErrorLog specifies an optional logger for errors
	// that occur when attempting to proxy the request.
	// If nil, logging is done via the log package's standard logger.
	ErrorLog *log.Logger

	// BufferPool optionally specifies a buffer pool to
	// get byte slices for use by io.CopyBuffer when
	// copying HTTP response bodies.
	BufferPool BufferPool

	// ModifyResponse is an optional function that modifies the
	// Response from the backend. It is called if the backend
	// returns a response at all, with any HTTP status code.
	// If the backend is unreachable, the optional ErrorHandler is
	// called without any call to ModifyResponse.
	//
	// If ModifyResponse returns an error, ErrorHandler is called
	// with its error value. If ErrorHandler is nil, its default
	// implementation is used.
	ModifyResponse func(*http.Response) error

	// ErrorHandler is an optional function that handles errors
	// reaching the backend or errors from ModifyResponse.
	//
	// If nil, the default is to log the provided error and return
	// a 502 Status Bad Gateway response.
	ErrorHandler func(http.ResponseWriter, *http.Request, error)

	Filters []NamingFilter
	Context context.Context
}

ReverseProxy is an HTTP Handler that takes an incoming request and sends it to another server, proxying the response back to the client.

ReverseProxy by default sets the client IP as the value of the X-Forwarded-For header.

If an X-Forwarded-For header already exists, the client IP is appended to the existing values. As a special case, if the header exists in the Request.Header map but has a nil value (such as when set by the Director func), the X-Forwarded-For header is not modified.

To prevent IP spoofing, be sure to delete any pre-existing X-Forwarded-For header coming from the client or an untrusted proxy.

func (*ReverseProxy) Clone

func (p *ReverseProxy) Clone() *ReverseProxy

func (*ReverseProxy) ServeHTTP

func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request)

type Signal

type Signal int
const (
	Continue Signal = iota
	Intercept
)

func (Signal) String

func (s Signal) String() string

type TimerTransport

type TimerTransport struct {
	Logger logs.Logger
	Inner  http.RoundTripper
}

func (*TimerTransport) RoundTrip

func (t *TimerTransport) RoundTrip(req *http.Request) (*http.Response, error)

type Writer

type Writer interface {
	io.Writer
	io.ByteWriter
}

Jump to

Keyboard shortcuts

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