Documentation
¶
Overview ¶
Package capture defines the protocol-agnostic traffic model (Flow, Message) and a thread-safe Store that the UI subscribes to. Nothing in this package knows about HTTP, TLS, or bubbletea — it is the shared vocabulary the proxy, the protocol parsers, and the TUI all speak.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DecodeContentEncoding ¶
DecodeContentEncoding decompresses a body per its Content-Encoding header (gzip, deflate, br, zstd). Empty/identity/unknown encodings and any decode error return the input unchanged, so display is always best-effort and never fails.
Types ¶
type Direction ¶
type Direction int
Direction distinguishes client→server bytes from server→client bytes. It is the only orientation concept streaming protocols (WebSocket, gRPC, raw TCP) need, and request/response protocols map cleanly onto it too.
type Event ¶
Event describes a change to the Store. The TUI translates these into tea.Msg values so the Elm-style update loop stays the single UI writer.
type Flow ¶
type Flow struct {
ID string
Protocol Protocol
ClientAddr string
ServerAddr string // host:port as the client requested it
SNI string // TLS server name, empty for plaintext
Secure bool // was this connection TLS-terminated by us?
StartedAt time.Time
Status Status
Flagged bool // user-marked as interesting (UI-only; survives session save)
Err error `json:"-"` // an error interface can't round-trip through JSON
// Request/Response for request-response protocols.
Request *Message
Response *Message
// Messages for streaming protocols (ordered). Guard appends with
// AddMessage: streaming protocols pump both directions concurrently.
Messages []*Message
// contains filtered or unexported fields
}
Flow is one logical exchange over one connection.
func (*Flow) AddMessage ¶
AddMessage appends a streaming message under a lock, so the two per-direction pump goroutines of a streaming protocol don't race.
type Injector ¶
Injector pushes a frame into a live bidirectional session (currently WebSocket). Direction chooses which peer receives it; opcode and payload are protocol-specific (a WebSocket opcode and its bytes). Implemented by the protocol handler for an active connection.
type Message ¶
type Message struct {
Direction Direction
Timestamp time.Time
// Summary is the one-line human view, e.g. "GET /v1/users HTTP/1.1" or
// "200 OK (1.2 KB)". Parsers fill this in.
Summary string
Headers map[string][]string
Body []byte
// Raw is the full serialized message exactly as it went (or will go) on the
// wire — request line + headers + body for HTTP, the frame payload for
// streaming protocols. It is what the tamper editor seeds from and what an
// edited Resolution.EditedBody replaces.
Raw []byte
// Meta carries protocol-specific fields that don't fit Headers/Body
// (gRPC status, WS opcode, HTTP method/path, …).
Meta map[string]string
}
Message is one parsed unit of traffic. For request/response protocols a Flow has one client Message (the request) and one server Message (the response). For streaming protocols a Flow accumulates many Messages in order.
type SessionRegistrar ¶
type SessionRegistrar interface {
RegisterSession(flowID string, inj Injector)
UnregisterSession(flowID string)
}
SessionRegistrar is an optional capability a Tamperer may also implement. Streaming protocol handlers type-assert their tamper to it and register their live session so the UI can inject into it; a tamper that doesn't support injection simply won't satisfy the assertion.
type Status ¶
type Status int
Status tracks a Flow through the intercept lifecycle.
const ( // StatusActive: bytes are flowing, nothing is paused. StatusActive Status = iota // StatusPending: matched an intercept rule and is paused awaiting a user // decision (forward / drop / edit). StatusPending // StatusComplete: the exchange finished normally. StatusComplete // StatusError: the connection or parse failed; see Flow.Err. StatusError )
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the thread-safe home for every captured Flow. The proxy writes; the UI reads and subscribes. It intentionally keeps flows in insertion order so the list pane is stable.
func (*Store) List ¶
List returns a snapshot of flows in insertion order. Callers get copies of the slice, not the underlying flows, so iteration is race-free even while the proxy keeps mutating flow contents.