proxy

package
v0.1.19 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 48 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrEmptyRequest    = errors.New("empty request")
	ErrEmptyResponse   = errors.New("empty response")
	ErrInvalidRequest  = errors.New("invalid request line")
	ErrInvalidResponse = errors.New("invalid status line")
)

Functions

func ApplyRawQueryModifications added in v0.1.6

func ApplyRawQueryModifications(query string, remove []string, set []string) string

ApplyRawQueryModifications applies set and remove operations to a raw query string without parsing/re-encoding, preserving parameter order and percent-encoding.

func BuildInterceptedH1Response added in v0.1.11

func BuildInterceptedH1Response(intercepted *InterceptedResponse) *types.RawHTTP1Response

BuildInterceptedH1Response converts an InterceptedResponse to a wire-serializable RawHTTP1Response. Computes Content-Length when the responder set no framing header so keep-alive clients don't hang on connection-close framing.

func CheckLineEndings

func CheckLineEndings(raw []byte) string

CheckLineEndings detects line ending issues in HTTP headers. Returns a description of the issue, or empty string if OK.

func Compress

func Compress(data []byte, encoding string) ([]byte, error)

Compress compresses data with the specified encoding. Returns (compressed data, error). Unknown encodings return the original data unchanged.

Handles the same normalization as Decompress for consistency.

func ContainsHeader added in v0.1.6

func ContainsHeader(entries []string, name string) bool

ContainsHeader checks if any "Name: Value" entry matches the given header name (case-insensitive).

func Decompress

func Decompress(data []byte, encoding string) ([]byte, bool)

Decompress decompresses data based on Content-Encoding. Returns (decompressed data, wasCompressed). If wasCompressed is true but returned data is nil, decompression failed. Unknown encodings return (original data, false).

Handles: - Case variations: "GZIP", "Gzip" normalized to "gzip" - Whitespace: " gzip " trimmed - x-gzip alias: treated as gzip - deflate: tries raw DEFLATE first, then zlib-wrapped - br: Brotli decompression - zstd: Zstandard decompression - Multiple encodings (e.g., "gzip, br"): skipped (can't partially decode)

func ExtractMethod added in v0.1.6

func ExtractMethod(raw []byte) string

ExtractMethod extracts the HTTP method from raw request bytes. Returns the first space-delimited token from the request line. Handles both CRLF and bare-LF line endings. Defaults to "GET" for empty input or lines without a space.

func FilterSupportedEncodings added in v0.1.12

func FilterSupportedEncodings(acceptEncoding string) string

FilterSupportedEncodings filters an Accept-Encoding header value to only include encodings the proxy can decompress/recompress. Preserves quality values and ordering. Falls back to all supported encodings when the input contains no encoding supported by the proxy.

func NormalizeEncoding

func NormalizeEncoding(encoding string) (string, bool)

NormalizeEncoding normalizes a Content-Encoding header value. Returns the normalized encoding and whether it's a single supported encoding. Multiple encodings (e.g., "gzip, br") return ("", false) since we can't partially decode.

func ParseRequest added in v0.1.11

func ParseRequest(r io.Reader) (*types.RawHTTP1Request, error)

ParseRequest parses an HTTP/1.1 request from the reader. Returns error only for truly unparseable input.

func ParseRequestLine

func ParseRequestLine(line []byte) (method, path, query, version string, err error)

ParseRequestLine extracts method, path, query, version from request line. Accepts malformed lines if method and path are extractable.

func PathWithoutQuery

func PathWithoutQuery(p string) string

PathWithoutQuery returns the path portion before any query string.

Types

type CaptureFilter added in v0.1.6

type CaptureFilter func(flow *types.Flow) bool

CaptureFilter decides whether a flow should be stored. Returns true if the flow should be captured, false to discard.

type CertManager

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

CertManager handles CA certificate loading/generation and on-demand certificate generation for HTTPS MITM interception.

func (*CertManager) CACert

func (m *CertManager) CACert() *x509.Certificate

CACert returns the CA certificate for clients to trust.

func (*CertManager) Close

func (m *CertManager) Close() error

Close releases resources held by the cert cache.

func (*CertManager) GetCertificate

func (m *CertManager) GetCertificate(hostname string, spec *types.CertSpec) (*tls.Certificate, error)

GetCertificate returns a certificate for the hostname, whose SANs additionally include any names in spec (nil spec yields a single-SAN leaf). Generates and caches if not already cached.

type HeaderGroup added in v0.1.6

type HeaderGroup struct {
	Key     string   // lowercase header name
	Entries []string // original "Name: Value" strings
}

HeaderGroup represents headers sharing the same name (case-insensitive).

func GroupHeaderEntries added in v0.1.6

func GroupHeaderEntries(entries []string) []HeaderGroup

GroupHeaderEntries groups "Name: Value" strings by header name (case-insensitive), preserving insertion order.

type HistoryStore

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

HistoryStore provides typed access to proxy history backed by store.Storage. Entries are keyed by flow_id; merge ordering uses (Timestamp, FlowID).

func (*HistoryStore) Children added in v0.1.18

func (h *HistoryStore) Children(parentFlowID string) []*types.Flow

Children returns the child flows of parentFlowID in emission order.

func (*HistoryStore) Close

func (h *HistoryStore) Close()

Close closes the underlying storage.

func (*HistoryStore) Complete added in v0.1.18

func (h *HistoryStore) Complete(flowID string, resp *types.Message, completedAt time.Time, annotations map[string]any) bool

Complete attaches a late response and/or completion to an already-stored flow: the two-phase form used for deferred responses and session/stream teardown. resp, when non-nil, populates the response side; a non-zero completedAt sets CompletedAt; annotations merge over existing keys. Returns false when flowID is unknown.

func (*HistoryStore) Count

func (h *HistoryStore) Count() int

Count returns the number of entries currently stored.

func (*HistoryStore) Delete added in v0.1.15

func (h *HistoryStore) Delete(flowIDs ...string) int

Delete removes entries by flow_id. Idempotent; unknown ids are skipped. Returns the number of entries actually removed.

func (*HistoryStore) Get

func (h *HistoryStore) Get(flowID string) (*types.Flow, bool)

Get retrieves a flow by flow_id.

func (*HistoryStore) GetMeta

func (h *HistoryStore) GetMeta(flowID string) (*types.HistoryMeta, bool)

GetMeta retrieves lightweight metadata for an entry by flow_id.

func (*HistoryStore) Page added in v0.1.15

func (h *HistoryStore) Page(count int, afterFlowID string) []*types.Flow

Page returns up to count flows strictly after afterFlowID, ordered oldest-first.

func (*HistoryStore) PageMeta added in v0.1.15

func (h *HistoryStore) PageMeta(count int, afterFlowID string) []types.HistoryMeta

PageMeta returns up to count meta entries strictly after afterFlowID, ordered oldest-first.

func (*HistoryStore) SetCaptureFilter added in v0.1.6

func (h *HistoryStore) SetCaptureFilter(f CaptureFilter)

SetCaptureFilter sets the filter checked by ShouldCapture. Callers of Store are responsible for checking ShouldCapture first.

func (*HistoryStore) SetInvokedBy added in v0.1.18

func (h *HistoryStore) SetInvokedBy(flowID, invokedBy string) bool

SetInvokedBy records the originating sidecar on an already-stored flow. Returns false when flowID is unknown.

func (*HistoryStore) ShouldCapture added in v0.1.6

func (h *HistoryStore) ShouldCapture(flow *types.Flow) bool

ShouldCapture returns true if the flow passes the capture filter, or true when no filter is configured.

func (*HistoryStore) Store

func (h *HistoryStore) Store(flow *types.Flow) string

Store mints a flow_id, assigns it to flow, persists, and returns the flow_id. flow.StartedAt must be set by the caller. Child flows (ParentFlowID set) are stored payload-only: no meta key and absent from the listing order.

type InterceptedResponse added in v0.1.11

type InterceptedResponse struct {
	StatusCode int
	Headers    types.Headers
	Body       []byte
}

InterceptedResponse is a canned response to serve for an intercepted request.

type Modifications

type Modifications struct {
	Method        string            // Override HTTP method
	SetHeaders    []string          // "Name: Value" format; duplicates supported
	RemoveHeaders []string          // Remove headers by name
	Body          []byte            // Replace entire body (mutually exclusive with JSON mods)
	SetJSON       map[string]any    // Modify JSON fields
	RemoveJSON    []string          // Remove JSON fields
	SetParams     map[string]string // Set query parameters
	RemoveParams  []string          // Remove query parameters
}

Modifications specifies changes to apply to a request.

type ProxyServer

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

ProxyServer is an HTTP proxy server that captures request/response pairs.

func NewProxyServer

func NewProxyServer(port int, configDir string, maxBodyBytes int, historyStorage store.Storage, timeouts TimeoutConfig) (*ProxyServer, error)

NewProxyServer creates a new proxy server with HTTPS MITM support. configDir is the directory for CA certificates (e.g., ~/.sectool). maxBodyBytes limits request and response body sizes stored in history. historyStorage is the storage backend for proxy history entries.

func (*ProxyServer) Addr

func (s *ProxyServer) Addr() string

Addr returns the proxy listener address (e.g., "127.0.0.1:12345").

func (*ProxyServer) CertManager

func (s *ProxyServer) CertManager() *CertManager

CertManager returns the certificate manager for external access.

func (*ProxyServer) History

func (s *ProxyServer) History() *HistoryStore

History returns the history store for external access.

func (*ProxyServer) Registry added in v0.1.18

func (s *ProxyServer) Registry() *protocol.Registry

Registry returns the per-connection claim registry.

func (*ProxyServer) Serve

func (s *ProxyServer) Serve() error

Serve starts accepting connections. Blocks until shutdown.

func (*ProxyServer) SetCaptureFilter added in v0.1.6

func (s *ProxyServer) SetCaptureFilter(f CaptureFilter)

SetCaptureFilter sets the capture filter for the proxy history. Entries rejected by the filter are still proxied but not stored.

func (*ProxyServer) SetResponseInterceptor added in v0.1.11

func (s *ProxyServer) SetResponseInterceptor(interceptor ResponseInterceptor)

SetResponseInterceptor sets the response interceptor for HTTP handlers. Call after construction but before Serve().

func (*ProxyServer) SetRuleApplier

func (s *ProxyServer) SetRuleApplier(applier types.RuleApplier)

SetRuleApplier sets the rule applier for all handlers. Call after construction but before Serve().

func (*ProxyServer) Shutdown

func (s *ProxyServer) Shutdown(ctx context.Context) error

Shutdown gracefully stops the server.

func (*ProxyServer) WaitReady

func (s *ProxyServer) WaitReady(ctx context.Context) error

WaitReady blocks until Serve() has entered its accept loop.

type ResponseInterceptor added in v0.1.11

type ResponseInterceptor interface {
	// InterceptRequest checks if a request matches a registered responder.
	// host is the target hostname (lowercase), port is the target port,
	// path is the URL path (query string stripped), method is the HTTP method.
	// Returns the response to serve, or nil if no match.
	InterceptRequest(host string, port int, path string, method string) *InterceptedResponse
}

ResponseInterceptor checks if a request should be intercepted with a canned response. Implementations must be safe for concurrent use and fast (no I/O on the hot path).

type SendOptions

type SendOptions struct {
	RawRequest    []byte         // Raw HTTP request bytes
	Target        types.Target   // Where to send
	Modifications *Modifications // Optional changes
	Force         bool           // Bypass validation

	// Protocol specifies the original request's protocol.
	// Values: "http/1.1", "http/2", or "" (defaults to http/1.1)
	// When "http/2", the sender will negotiate HTTP/2 with the server.
	Protocol string
}

SendOptions configures request sending.

type SendResult

type SendResult struct {
	Response *types.RawHTTP1Response
	Duration time.Duration

	// ModifiedRequest holds the first hop's post-rule request bytes, set only when rules
	// changed the request. nil when no RequestRuleApplier ran or it made no change.
	ModifiedRequest []byte
}

type Sender

type Sender struct {
	// RequestRuleApplier applies find/replace rules to each request before sending.
	// Called for every request including redirect hops. If nil, no rules are applied.
	RequestRuleApplier func(req *types.RawHTTP1Request) *types.RawHTTP1Request

	// Timeouts holds configurable timeout values for dial, read, and write.
	// Zero values mean no timeout.
	Timeouts TimeoutConfig
}

Sender sends HTTP requests with wire-level fidelity.

func (*Sender) Send

func (s *Sender) Send(ctx context.Context, opts SendOptions) (*SendResult, error)

Send sends a request and returns the response.

func (*Sender) SendWithRedirects

func (s *Sender) SendWithRedirects(ctx context.Context, opts SendOptions) (*SendResult, error)

SendWithRedirects sends a request and follows redirects.

type TimeoutConfig

type TimeoutConfig struct {
	DialTimeout  time.Duration
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
}

TimeoutConfig holds configurable timeout values for proxy operations.

Directories

Path Synopsis
Package types holds the proxy capture data model: the wire-fidelity HTTP/1.1 request/response types, the common Flow/Message envelope, and the rule-applier contract.
Package types holds the proxy capture data model: the wire-fidelity HTTP/1.1 request/response types, the common Flow/Message envelope, and the rule-applier contract.

Jump to

Keyboard shortcuts

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