har

package
v1.57.0 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: Apache-2.0 Imports: 18 Imported by: 8

Documentation

Overview

Package har provides HAR 1.2 types and an HTTP client middleware for capturing outbound request/response pairs for troubleshooting.

Index

Constants

View Source
const CreatorName = "flanksource-commons"

CreatorName identifies commons as the producer in the HAR envelope.

View Source
const MaxBodySizeProperty = "http.har.maxBodySize"

MaxBodySizeProperty is the -P/properties key that overrides the default per-body capture cap (in bytes). Set e.g. -P http.har.maxBodySize=1048576 to capture request/response bodies larger than the 64 KB default, or -P http.har.maxBodySize=0 to capture full bodies with no cap.

View Source
const PropertyPrefix = "http."

PropertyPrefix is the namespace the registry resolves its properties under.

View Source
const SensitiveProperty = "http.har.sensitive"

SensitiveProperty is the -P/properties key that disables redaction. By default credentials in headers, bodies and query strings are masked, so a HAR file is safe to share but cannot be replayed. Set -P http.har.sensitive=true to capture them verbatim — the resulting file holds live secrets and is written with 0600.

Variables

This section is empty.

Functions

func NewMetadataMiddleware added in v1.55.0

func NewMetadataMiddleware(cfg HARConfig, handler func(*Entry)) middlewares.Middleware

NewMetadataMiddleware captures method, URL, sanitized headers, query string, status and timings — no request or response bodies. Body sizes use -1 per the HAR spec ("size unknown"). Use it when you want a HAR file for traffic analysis without paying the body-buffering cost.

Ported from duty/connection/common.go's metadataHARMiddleware, which commons/http and commons-db each carried their own copy of.

func NewMiddleware

func NewMiddleware(cfg HARConfig, handler func(*Entry)) middlewares.Middleware

NewMiddleware returns a middlewares.Middleware that captures each request/response pair into a *Entry and calls handler. If handler is nil, the middleware is a no-op.

func WriteFile added in v1.55.0

func WriteFile(collector *Collector, path string) error

WriteFile serializes collector.Entries() into a HAR 1.2 file at path. A collector configured with CaptureSensitive holds unmasked credentials, so its file is written 0600 rather than 0644.

Types

type Cache

type Cache struct{}

Cache holds cache information for an entry (required by spec; left empty by hx).

type Collector

type Collector struct {
	Config HARConfig
	// contains filtered or unexported fields
}

Collector accumulates HAR entries from multiple sources (main requests, OAuth token fetches, redirect hops, retries).

func NewCollector

func NewCollector(cfg HARConfig) *Collector

func NewCollectorWithHandler added in v1.57.0

func NewCollectorWithHandler(cfg HARConfig, handler func(*Entry)) *Collector

NewCollectorWithHandler creates a collector that retains its own bounded view and forwards every entry to handler. This lets a request-scoped diagnostic collector coexist with a longer-lived HAR export collector.

func (*Collector) Add

func (c *Collector) Add(e *Entry)

Add appends an entry to the collector. Safe for concurrent use.

func (*Collector) DroppedEntries added in v1.57.0

func (c *Collector) DroppedEntries() int

DroppedEntries returns the number of entries rejected after MaxEntries was reached.

func (*Collector) Entries

func (c *Collector) Entries() []Entry

Entries returns a copy of all collected entries.

func (*Collector) Handler

func (c *Collector) Handler() func(*Entry)

Handler returns a func(*Entry) that adds entries to this collector. Useful for passing to components that accept a HAR handler callback.

func (*Collector) Middleware

func (c *Collector) Middleware() middlewares.Middleware

Middleware returns a transport middleware that captures each request/response into this collector.

func (*Collector) Pretty added in v1.48.0

func (c *Collector) Pretty() api.Text

Pretty returns a compact summary of all collected entries.

func (*Collector) Table added in v1.48.0

func (c *Collector) Table() api.TextTable

Table returns a TextTable of all collected entries with row detail expansion.

type Content

type Content struct {
	Size      int64  `json:"size"`
	MimeType  string `json:"mimeType,omitempty"`
	Text      string `json:"text,omitempty"`
	Truncated bool   `json:"truncated,omitempty"`
}

Content holds the response body details.

type Cookie struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

Cookie is a name/value pair from a Cookie or Set-Cookie header.

type Creator

type Creator struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

Creator identifies the application that created the HAR log.

type DetailOptions added in v1.57.0

type DetailOptions struct {
	RequestHeaders  bool
	QueryString     bool
	RequestBody     bool
	ResponseHeaders bool
	ResponseBody    bool
}

type Entry

type Entry struct {
	StartedDateTime string   `json:"startedDateTime"`
	Time            float64  `json:"time"`
	Request         Request  `json:"request"`
	Response        Response `json:"response"`
	Cache           Cache    `json:"cache"`
	Timings         Timings  `json:"timings"`
}

Entry represents a single HTTP request/response pair.

func CaptureRedirect

func CaptureRedirect(req *http.Request, resp *http.Response, cfg HARConfig) *Entry

CaptureRedirect builds a HAR entry from a redirect hop's request and response.

func (Entry) Columns added in v1.48.0

func (e Entry) Columns() []api.ColumnDef

Columns implements api.TableProvider.

func (Entry) Detail added in v1.57.0

func (e Entry) Detail(options DetailOptions) api.Textable

Detail returns only the selected request and response sections.

func (Entry) Pretty added in v1.48.0

func (e Entry) Pretty() api.Text

Pretty returns a compact one-line summary.

func (Entry) Row added in v1.48.0

func (e Entry) Row() map[string]any

Row implements api.TableProvider.

func (Entry) RowDetail added in v1.48.0

func (e Entry) RowDetail() api.Textable

RowDetail implements api.DetailProvider for expandable table rows.

type File

type File struct {
	Log Log `json:"log"`
}

File is the outermost HAR 1.2 envelope: {"log": {...}}. Use this when writing .har files for import into browser DevTools.

type HARConfig

type HARConfig struct {
	// MaxEntries limits how many entries a Collector retains. Zero keeps all
	// entries, which preserves the existing HAR-file behavior. Request-scoped
	// diagnostics set an explicit bound.
	MaxEntries int

	// MaxBodySize is the maximum number of bytes captured per body.
	// Bodies exceeding this are truncated and Content.Truncated is set to true.
	// Default: 65536 (64 KB).
	MaxBodySize int64

	// CaptureContentTypes lists MIME type prefixes for which body capture is enabled.
	// Default: ["application/json", "application/x-www-form-urlencoded"].
	CaptureContentTypes []string

	// RedactedHeaders lists additional header name glob patterns to redact,
	// on top of logger.CommonRedactedHeaders.
	RedactedHeaders []string

	// RedactedBodyKeys lists additional key names (case-insensitive substring
	// match) to redact from request/response bodies (JSON and form) and from
	// URL query strings, on top of logger.SensitiveKeys. Use for app-specific
	// identifiers (e.g. session ids, national-id fields) that the default
	// heuristics don't recognise.
	RedactedBodyKeys []string

	// CaptureSensitive records credentials verbatim instead of masking them,
	// so the archive can be replayed against the live API. Honours
	// SensitiveProperty; off by default.
	CaptureSensitive bool
}

HARConfig controls what the HAR middleware captures and how it redacts.

func DefaultConfig

func DefaultConfig() HARConfig

DefaultConfig returns a HARConfig with sensible defaults. The per-body capture cap honours the MaxBodySizeProperty (-P http.har.maxBodySize=…) override; an unset or unparseable value keeps the 64 KB default, and a value <= 0 disables truncation (full bodies captured).

type Header struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

Header is a name/value pair.

type Level added in v1.55.0

type Level int

Level selects what a HAR collector captures. Borrowed from duty/connection/common.go's Debug/Trace split: at Metadata only headers, query strings and timings are recorded (no bodies, so no body re-read cost); at Full the standard collector middleware captures bodies too.

const (
	Disabled Level = iota
	Metadata
	Full
)

func ParseLevel added in v1.55.0

func ParseLevel(value string, def Level) (Level, error)

ParseLevel maps a property value onto a Level. "debug"/"trace" are accepted as synonyms for metadata/full, matching the log.level.*.har vocabulary duty and commons-db use. An empty string yields def; anything unrecognised is an error, so a typo turns into a startup failure rather than silently capturing the wrong thing.

func (Level) String added in v1.55.0

func (l Level) String() string

type Log

type Log struct {
	Version string  `json:"version"`
	Creator Creator `json:"creator"`
	Pages   []Page  `json:"pages"`
	Entries []Entry `json:"entries"`
}

Log is the top-level HAR 1.2 container.

type Page

type Page struct {
	StartedDateTime string      `json:"startedDateTime"`
	ID              string      `json:"id"`
	Title           string      `json:"title"`
	PageTimings     PageTimings `json:"pageTimings"`
}

Page is included for HAR 1.2 spec compliance; hx leaves it empty.

type PageTimings

type PageTimings struct {
	OnLoad int `json:"onLoad,omitempty"`
}

PageTimings holds page-level timing data (unused by hx, present for spec compliance).

type PostData

type PostData struct {
	MimeType string `json:"mimeType"`
	Text     string `json:"text"`
}

PostData holds the request body details.

type QueryString

type QueryString struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}

QueryString is a name/value pair from the URL query string.

type Registry added in v1.55.0

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

Registry turns -P properties into HAR capture: it resolves the output path and level per feature, owns one collector per output file, and writes them all on Flush.

Properties are looked up per-feature first, then globally:

http.<feature>.har        / http.har        output path; unset disables capture
http.<feature>.har.level  / http.har.level  "full" (default) or "metadata"
http.har.sensitive                          capture credentials verbatim
http.har.maxBodySize                        per-body capture cap

Collectors are deduplicated by absolute path, so several features writing to the same file share one archive.

func NewRegistry added in v1.55.0

func NewRegistry(log logger.Logger) *Registry

NewRegistry returns a registry that announces capture as it is enabled and reports flush results on log. Pass nil for the shared "har" logger, whose level can be raised on its own with -Plog.level.har=debug.

func (*Registry) Flush added in v1.55.0

func (r *Registry) Flush() error

Flush writes every collector to its file. Collectors are kept afterwards, so a second call rewrites the same files rather than losing entries.

func (*Registry) For added in v1.55.0

func (r *Registry) For(feature string) (*Collector, string, Level, error)

For reports the collector, absolute output path and level configured for feature. A nil collector means capture is off. The shape matches http.CommonsHTTPContext's HARFor apart from the error, which reports an unusable http.har.level rather than silently capturing the wrong thing.

func (*Registry) Transport added in v1.55.0

func (r *Registry) Transport(feature string, base http.RoundTripper) (http.RoundTripper, error)

Transport wraps base with the capture middleware configured for feature, or returns base unchanged when capture is off.

type Request

type Request struct {
	Method      string        `json:"method"`
	URL         string        `json:"url"`
	HTTPVersion string        `json:"httpVersion"`
	Cookies     []Cookie      `json:"cookies"`
	Headers     []Header      `json:"headers"`
	QueryString []QueryString `json:"queryString"`
	PostData    *PostData     `json:"postData,omitempty"`
	HeadersSize int           `json:"headersSize"`
	BodySize    int64         `json:"bodySize"`
}

Request holds HAR request data.

type Response

type Response struct {
	Status      int      `json:"status"`
	StatusText  string   `json:"statusText"`
	HTTPVersion string   `json:"httpVersion"`
	Cookies     []Cookie `json:"cookies"`
	Headers     []Header `json:"headers"`
	Content     Content  `json:"content"`
	RedirectURL string   `json:"redirectURL"`
	HeadersSize int      `json:"headersSize"`
	BodySize    int64    `json:"bodySize"`
}

Response holds HAR response data.

type Timings

type Timings struct {
	Send    float64 `json:"send"`
	Wait    float64 `json:"wait"`
	Receive float64 `json:"receive"`
}

Timings records durations (in milliseconds) for the request lifecycle.

Jump to

Keyboard shortcuts

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