proxy

package
v0.82.260821 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

README

proxy

proxy 是 dp 的代理执行核心,负责保存已编译的 PreparedDirective,并把其中固定的 Plan 应用到 httputil.ReverseProxy

职责

  • 定义 PreparedDirectivePlanResolver、header 操作和代理错误。
  • resolver 只执行一次;ErrNoMatch 请求直接交给可选的下一个 HTTP handler。
  • PreparedDirective 固定持有 Source、Plan、Program、Recovery 和 Metadata;Plan 只拥有 HTTP 执行字段,后续 RoundTrip 不重新解析或比较 Plan。
  • 使用 resolver 已编译的最终上游 URL,应用请求 header 基线策略,并按顺序执行 exact 和 glob header rewrite。
  • 在最终上游响应写回客户端前应用 response header rewrite,同时保护连接级、framing 和 dp 系统 header。
  • patch 从原始入站请求重建端到端 header,同时始终剥离 HTTP hop-by-hop header。
  • 按 directive 中的 SOCKS5 配置选择 per-request upstream proxy。
  • HTTPS upstream 显式启用并优先协商 HTTP/2,服务端不支持时回退 HTTP/1.1;明文 HTTP 不隐式启用 h2c。
  • 保持 data plane 使用原生 net/http,避免影响流式响应。

业务协议解析不放在这里;internal/core/directive 负责把 inline Payload 或 remote RemoteSpec -> Payload 编译成 PreparedDirective。只有 resolver 匹配的请求才会进入 observer 或执行反向代理。

Documentation

Overview

Package proxy provides a reusable dynamic reverse proxy handler.

The package is independent of application-level request formats. Callers supply a Resolver that converts an incoming request into a Plan, and the handler applies that plan to a standard reverse proxy.

Example:

handler := proxy.NewHandler(resolver, transport, proxy.HandlerOptions{})
_ = handler

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrResolverFailed       = errors.New("proxy directive resolver failed")
	ErrBodyStoreUnavailable = errors.New("proxy request body replay store is unavailable")
	ErrModuleFailed         = errors.New("proxy module failed")
	ErrRecoveryFailed       = errors.New("proxy recovery failed")
)
View Source
var (
	ErrNoMatch                    = errors.New("proxy resolver did not match request")
	ErrInvalidDirective           = errors.New("invalid proxy directive")
	ErrDirectiveUnauthorized      = errors.New("directive token unauthorized")
	ErrDirectiveNotFound          = errors.New("directive reference not found")
	ErrRemoteDirectiveUnavailable = errors.New("remote directive unavailable")
	ErrDirectiveTokenTooLarge     = errors.New("directive token is too large")
	ErrRemoteDirectiveInvalid     = errors.New("remote directive is invalid")
)

Functions

func BuildRoundTripRequest added in v0.67.260718

func BuildRoundTripRequest(template *RequestTemplate, plan *Plan, ctx context.Context, body io.ReadCloser) *http.Request

func IsResponseHeaderProtected

func IsResponseHeaderProtected(name string) bool

func NewProxyAwareTransport

func NewProxyAwareTransport(base *http.Transport) *http.Transport

func NewProxyAwareTransportWithOptions

func NewProxyAwareTransportWithOptions(base *http.Transport, opts ProxyTransportOptions) *http.Transport

func WithRequestProxy

func WithRequestProxy(req *http.Request, proxyURL *url.URL) *http.Request

func WriteProxyErrorJSON

func WriteProxyErrorJSON(w http.ResponseWriter, status int, code, message string)

Types

type BodyPolicy added in v0.71.260719

type BodyPolicy struct {
	MaxBodyBytes int64         // -1 means inherit instance default.
	QueueWait    time.Duration // -1 means inherit instance default.
	ReadTimeout  time.Duration // -1 means inherit instance default.
	ChunkBytes   int           // -1 means inherit instance default.
}

type DirectiveSource added in v0.67.260718

type DirectiveSource struct {
	Mode          string
	Backend       string
	UUID          string
	Endpoint      string
	Resource      string
	Duration      time.Duration
	PayloadSHA256 string
}

type Handler

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

func NewHandler

func NewHandler(resolver Resolver, transport http.RoundTripper, opts HandlerOptions) *Handler
Example
package main

import (
	"net/http"
	"net/url"

	"github.com/lwmacct/260628-directive-proxy/internal/core/httpheader"
)

type staticResolver struct{}

func (staticResolver) Prepare(*http.Request) (*PreparedDirective, error) {
	target, _ := url.Parse("https://api.example.com/v1")
	return NewPreparedDirective(DirectiveSource{Mode: "inline"}, &Plan{
		Target: target,
		Headers: httpheader.Plan{Request: httpheader.RequestPlan{Ops: []httpheader.Op{{
			Action: httpheader.ActionSet,
			Selector: httpheader.Selector{
				Kind:    httpheader.SelectorExact,
				Pattern: "Authorization",
			},
			Values: []string{"Bearer upstream-token"},
		}}}},
	}, nil, nil, proxyTestMetadata())
}

func main() {
	handler := NewHandler(staticResolver{}, http.DefaultTransport, HandlerOptions{})
	_ = handler
}

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type HandlerOptions

type HandlerOptions struct {
	ExchangeFactory    exchangeStarter
	TrackBeforeResolve bool
	BodyStore          *bodystore.Controller
	BodyReadTimeout    time.Duration
	BodyMaxBytes       int64
	BodyQueueWait      time.Duration
	BodyChunkBytes     int
	RequestMetrics     RequestMetrics
	// Next receives requests for which Resolver returns ErrNoMatch.
	Next http.Handler
}

type Plan

type Plan struct {
	Target  *url.URL
	Proxy   *url.URL
	Headers httpheader.Plan
}

func ClonePlan

func ClonePlan(in *Plan) *Plan

type PreparedDirective

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

PreparedDirective is one immutable compilation result. Remote dereference, Payload validation and Program compilation are complete before this value is constructed; every RoundTrip consumes the same Plan and Recovery policy.

func NewPreparedDirective added in v0.67.260718

func NewPreparedDirective(source DirectiveSource, plan *Plan, executable *program.Executable, policy *recovery.Policy, fields metadata.Set, bodyPolicy ...*BodyPolicy) (*PreparedDirective, error)

func (*PreparedDirective) BodyPolicy added in v0.71.260719

func (prepared *PreparedDirective) BodyPolicy() *BodyPolicy

func (*PreparedDirective) Metadata added in v0.67.260718

func (prepared *PreparedDirective) Metadata() metadata.Set

func (*PreparedDirective) Plan added in v0.67.260718

func (prepared *PreparedDirective) Plan() *Plan

func (*PreparedDirective) Program added in v0.67.260718

func (prepared *PreparedDirective) Program() *program.Executable

func (*PreparedDirective) Recovery added in v0.67.260718

func (prepared *PreparedDirective) Recovery() *recovery.Policy

func (*PreparedDirective) Source

func (prepared *PreparedDirective) Source() DirectiveSource

type ProxyTransportOptions

type ProxyTransportOptions struct {
	MaxIdleConns        int
	MaxIdleConnsPerHost int
	MaxConnsPerHost     int
	IdleConnTimeout     time.Duration
}

type RecoveryTransport added in v0.63.260717

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

func NewRecoveryTransport added in v0.63.260717

func NewRecoveryTransport(base http.RoundTripper, options RecoveryTransportOptions) (*RecoveryTransport, error)

func (*RecoveryTransport) RoundTrip added in v0.63.260717

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

type RecoveryTransportOptions added in v0.63.260717

type RecoveryTransportOptions struct {
	MaxRecoveryRoundTrips int
	MaxRecoveryElapsed    time.Duration
	MaxRecoveryBodyBytes  int64
}

type RequestMetrics added in v0.71.260719

type RequestMetrics interface {
	RequestStarted()
	RequestFinished(status int, outcome string, duration time.Duration, requestBodyBytes, responseBodyBytes int64)
}

type RequestTemplate

type RequestTemplate struct {
	Method           string
	URL              *url.URL
	Host             string
	Header           http.Header
	Trailer          http.Header
	TransferEncoding []string
	Proto            string
	ProtoMajor       int
	ProtoMinor       int
	ContentLength    int64
	Close            bool
	IdempotencyKey   string
}

RequestTemplate is an immutable snapshot of the original inbound request metadata. Bodies are replayed separately; every round trip is rebuilt from this snapshot so routing and header mutations cannot leak between round trips.

func NewRequestTemplate

func NewRequestTemplate(req *http.Request) *RequestTemplate

type Resolver

type Resolver interface {
	Prepare(*http.Request) (*PreparedDirective, error)
}

Jump to

Keyboard shortcuts

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