Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsMasked ¶
IsMasked reports whether s is a placeholder produced by masking.
Such a value carries no information a reader does not already have: the inferred format says "uuid" far more usefully than an example of "00000000-0000-0000-0000-000000000000" does. Callers building documentation from a masked recording can use this to leave the example out entirely.
func RedactsBodyKey ¶
RedactsBodyKey reports whether DefaultMasker redacts values held by key.
A masked string announces itself — the zero UUID and the asterisk run are recognisable by IsMasked — but a masked number does not: a redacted count becomes 0, which is indistinguishable from a genuine 0. The key is the only remaining signal, so callers documenting a masked recording can ask about it directly rather than guessing from the value.
Types ¶
type Interaction ¶
type Interaction struct {
Request Request `json:"request"`
Response Response `json:"response,omitzero"`
}
Interaction represents a single observed HTTP request/response pair.
type Interactions ¶
type Interactions []Interaction
Interactions represents a collection of interactions.
func InteractionsReadFile ¶
func InteractionsReadFile(path string) (Interactions, error)
func InteractionsUnmarshal ¶
func InteractionsUnmarshal(data []byte) (Interactions, error)
func InteractionsUnmarshalRead ¶
func InteractionsUnmarshalRead(r io.Reader) (Interactions, error)
func (Interactions) MarshalWrite ¶
func (ias Interactions) MarshalWrite(w io.Writer) error
func (Interactions) Mask ¶
func (ias Interactions) Mask()
Mask redacts sensitive values in place using DefaultMasker.
func (Interactions) MaskWith ¶
func (ias Interactions) MaskWith(m Masker)
MaskWith redacts sensitive values in place according to m.
func (Interactions) TrimResponseHeaders ¶
func (ias Interactions) TrimResponseHeaders()
TrimResponseHeaders removes response headers we don't need in place.
func (Interactions) WriteFile ¶
func (ias Interactions) WriteFile(path string) error
type Masker ¶
type Masker struct {
// HeaderKeys are header names whose values are redacted, in requests and
// responses alike. Matching is case-insensitive.
HeaderKeys []string
// BodyKeys are JSON object keys whose values are redacted wherever they
// occur in a request or response body. Matching is case-insensitive and
// exact: "id" does not match "ownerId". When a matching key holds an object
// or an array, the whole subtree below it is redacted.
BodyKeys []string
// IDKeys are keys holding identifiers, redacted only when the value looks
// machine-generated: a UUID, or a run of at least 16 characters that has no
// separators and contains a digit.
//
// Use this for keys far too common to redact outright. "id" holding an
// account UUID or a numeric account ID is caught, while "id" holding a
// structural name — Notion labels its title property "title" — is left alone.
IDKeys []string
// NameKeys are keys holding a person's name, replaced with "John Doe" when
// the value actually reads as one: two to four capitalised words of letters.
//
// The shape check matters as much as the key. Recorded data is full of
// capitalised phrases that are not people — company names, taxonomy labels,
// page titles — and replacing those would corrupt the fixture while
// protecting nobody.
NameKeys []string
// UsernameKeys are keys holding a handle, replaced with "johndoe" in the
// same case as the original: "friedamuster" becomes "johndoe",
// "FriedaMuster" becomes "JohnDoe", "@friedamuster" becomes "@johndoe".
//
// Casing is preserved because an API often stores the same handle several
// ways — Habitica keeps both username and lowerCaseUsername — and a
// replacement that flattened them would make the fixture describe something
// the API never returns.
UsernameKeys []string
// Values are literal strings redacted wherever they occur in a body,
// whatever key holds them. Use this for identifiers that live under keys too
// generic to redact wholesale — an account UUID appearing under "id",
// "ownerId" and "value" is caught by listing the UUID here, whereas listing
// those keys in BodyKeys would destroy unrelated data.
//
// Prefer the key-based fields where they suffice: a value listed here has to
// be written down somewhere, and a masker configured in tracked source would
// publish the very string it is meant to hide.
Values []string
// KeepEmails leaves e-mail addresses in place. By default any string that is
// an e-mail address is redacted wherever it occurs, whatever key holds it,
// because an address is personal data no matter where it was recorded and
// the key holding it is often too generic to list.
KeepEmails bool
}
Masker configures which recorded values Interactions.MaskWith redacts.
Redaction is shape-preserving: a masked e-mail address is replaced by another e-mail address, a masked UUID by another UUID, a masked number by a number. Schemas inferred from a masked recording therefore keep the types and formats they would have had from the original, so masking a cassette does not change the specification it produces — only the examples in it.
The placeholders describe one fictional person: John Doe, johndoe, john.doe@example.com. A reader who meets one of them recognises the rest.
func DefaultMasker ¶
func DefaultMasker() Masker
DefaultMasker returns the configuration used by Interactions.Mask: the headers and body keys that carry credentials in most APIs.
It knows nothing about which identifiers are yours. A recording that carries an account ID under a generic key such as "id" needs that key listed in Masker.IDKeys, or the value itself in Masker.Values.
type Request ¶
type Request struct {
Method string `json:"method"`
URL string `json:"url"`
Headers http.Header `json:"header,omitempty"`
Body Body `json:"body,omitempty"`
}
Request represents an observed HTTP request.
func NewRequest ¶
NewRequest creates a new Request out of an *http.Request. If the request has a body, it is drained and restored.
type Response ¶
type Response struct {
StatusCode int `json:"statusCode"`
Headers http.Header `json:"header,omitempty"`
Body Body `json:"body,omitempty"`
}
Response represents an observed HTTP response.
func NewResponse ¶
NewResponse creates a new Response out of an *http.Response. If the response has a body, it is drained and restored.