Documentation
¶
Overview ¶
Package proxy is the recording proxy of driftgate record: a reverse proxy that forwards every request to one service and hands each finished exchange to a callback, which turns it into a catalog candidate. It is a reverse proxy only: whatever URL or Host a client sends, the request goes to the service's base URL, through a transport that connects only to allowed hosts, so it cannot be used to reach anything else.
It answers only requests for its own address: a Host header that is not the listen address (in a loopback form, for a loopback listen address) is refused, which defeats DNS rebinding, where a page the developer has open points its own name at 127.0.0.1 to read the service through the proxy. A browser request from another site is refused too, but for a plain navigation (a link, the return from a sign-in provider), which is forwarded and not recorded; and a request that changes data, or opens a websocket, must come from a local origin. On an address that is not loopback, a browser sends no Sec-Fetch-Site over plain HTTP, so a request of another site's page cannot be told from the developer's: there a request is recorded only with a sign it comes from a page of the proxy's own address (Sec-Fetch-Site same-origin or none, or an Origin or Referer of that address), and any other is forwarded but not recorded.
The request body is kept in memory up to a cap, only until the exchange is handed over; a larger one passes through unrecorded. A response body is never kept: it is read only to scan it for personal data (so the entry is stored private; one over the cap or cut off counts as personal, as does one that is not text, an image or a PDF, which is not read). A gzip or deflate body is decoded for the scan, within the same cap, and one in another encoding (br, zstd) counts as personal; the client gets the body as the service sent it. A stream (an event stream, a websocket) passes through untouched.
Index ¶
Constants ¶
const MaxRecorded = 16 << 20
MaxRecorded caps the request and response bodies the proxy keeps in memory per exchange (the request to record it, the response to scan it for personal data). Without it every request in flight could hold up to httpx.MaxBody twice; a larger body still passes through, only unrecorded.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Exchange ¶
type Exchange struct {
// Entry is the request as the pipeline takes it, credentials included;
// Response is filled only for a response that may hold text.
Entry har.Entry
Status int
// Streamed says why the exchange passed through unrecorded: "event
// stream", "websocket", "stream" or "navigation from another site".
// Entry has only the method and URL then.
Streamed string
// Large: the request body was over the cap and is not in Entry.
Large bool
// Unverified: the proxy listens beyond loopback and the request had no
// sign it came from a page of the proxy's own address; it was forwarded,
// not recorded. Entry has only the method and URL then.
Unverified bool
}
Exchange is one request that went through the proxy and its outcome.
type Options ¶
type Options struct {
Target string // the service's base URL
// Listen is the address the proxy listens on, host:port with the port
// it got. Requests are answered only for that Host: in any loopback form
// (127.0.0.1, [::1], localhost) with that port, and for a host that is
// not loopback, that host exactly (any IP address for an unspecified
// one, such as 0.0.0.0: a rebound name is never an address).
Listen string
Allow *httpx.Allow
MaxBody int64 // request and scanned response bodies; default and at most MaxRecorded
// Skip names request paths that are forwarded but not recorded (static
// files are never recorded).
Skip func(path string) bool
Record func(Exchange) // called once the response is sent; may be called concurrently
}
Options configure the proxy.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is the proxy handler.
func New ¶
New builds the proxy handler. It checks that the target is an http or https URL; the caller checks it is on an allowed host before listening.
func (*Proxy) CloseIdleConnections ¶
func (p *Proxy) CloseIdleConnections()
CloseIdleConnections closes the idle connections to the service; call it once the server is shut down.