Documentation
¶
Overview ¶
Package har exports captured flows as HAR 1.2 documents and imports HAR documents produced by pano, browsers (Chrome, Firefox) and other proxies.
Export streams entries one at a time so a large capture never has to be held in memory twice. Bodies are looked up on demand through a BodyFunc, which must return decoded bytes (Content-Encoding removed); text bodies are inlined as UTF-8, everything else is base64. An optional Redactor masks secrets in header values and text bodies before they reach the writer.
Each exported entry carries a "_pano" extension object (HAR permits underscore-prefixed custom fields) holding the flow id, kind, session, error, tags, rule hits and truncation flags. Import restores those fields when present and falls back to sensible defaults for HARs produced elsewhere.
The Log, Entry and related types mirror the HAR 1.2 schema and are exported so callers can inspect or build documents directly.
Index ¶
- Constants
- Variables
- func Export(w io.Writer, flows []*flow.Flow, opts ExportOptions) (int, error)
- type BodyFunc
- type Cache
- type CacheState
- type Content
- type Cookie
- type Creator
- type Document
- type Entry
- type ExportOptions
- type Imported
- type Log
- type NVP
- type Page
- type PageTimings
- type PanoExt
- type Param
- type PostData
- type Redactor
- type Request
- type Response
- type Timings
Constants ¶
const DefaultMaxBodyBytes = 1 << 20
DefaultMaxBodyBytes is the per-body inline cap used when ExportOptions.MaxBodyBytes is zero.
const Version = "1.2"
Version is the HAR format version this package writes.
Variables ¶
var ErrNotHAR = errors.New("har: document has no log object")
ErrNotHAR is returned when the input parses as JSON but has no "log" object.
Functions ¶
Types ¶
type BodyFunc ¶
BodyFunc fetches a body's decoded bytes (Content-Encoding removed) by hash. It returns ok=false when the body is unavailable.
type Cache ¶
type Cache struct {
BeforeRequest *CacheState `json:"beforeRequest,omitempty"`
AfterRequest *CacheState `json:"afterRequest,omitempty"`
Comment string `json:"comment,omitempty"`
}
Cache describes cache usage; pano always writes an empty object.
type CacheState ¶
type CacheState struct {
Expires string `json:"expires,omitempty"`
LastAccess string `json:"lastAccess"`
ETag string `json:"eTag"`
HitCount int64 `json:"hitCount"`
Comment string `json:"comment,omitempty"`
}
CacheState is a cache entry snapshot.
type Content ¶
type Content struct {
Size int64 `json:"size"`
Compression *int64 `json:"compression,omitempty"`
MimeType string `json:"mimeType"`
Text string `json:"text,omitempty"`
Encoding string `json:"encoding,omitempty"`
Comment string `json:"comment,omitempty"`
}
Content is a response body. Size is the decoded length; Encoding is "base64" when Text is base64 rather than literal text.
type Cookie ¶
type Cookie struct {
Name string `json:"name"`
Value string `json:"value"`
Path string `json:"path,omitempty"`
Domain string `json:"domain,omitempty"`
Expires string `json:"expires,omitempty"`
HTTPOnly bool `json:"httpOnly,omitempty"`
Secure bool `json:"secure,omitempty"`
Comment string `json:"comment,omitempty"`
}
Cookie is a parsed request or response cookie.
type Creator ¶
type Creator struct {
Name string `json:"name"`
Version string `json:"version"`
Comment string `json:"comment,omitempty"`
}
Creator identifies the application that produced the log.
type Document ¶
type Document struct {
Log *Log `json:"log"`
}
Document is a HAR file: a single "log" object.
type Entry ¶
type Entry struct {
Pageref string `json:"pageref,omitempty"`
StartedDateTime string `json:"startedDateTime"`
Time float64 `json:"time"`
Request Request `json:"request"`
Response Response `json:"response"`
Cache Cache `json:"cache"`
Timings Timings `json:"timings"`
ServerIPAddress string `json:"serverIPAddress"`
Connection string `json:"connection,omitempty"`
Comment string `json:"comment,omitempty"`
// Pano is the "_pano" extension carrying flow metadata that has no HAR
// equivalent. It is nil on documents written by other tools.
Pano *PanoExt `json:"_pano,omitempty"`
}
Entry is one exchange.
type ExportOptions ¶
type ExportOptions struct {
// Creator and Version populate log.creator.
Creator, Version string
// Body resolves body hashes to decoded bytes. When nil no bodies are
// inlined and each body carries an explanatory comment.
Body BodyFunc
// Redact, when non-nil, masks header values and text bodies.
Redact *Redactor
// MaxBodyBytes caps the size of a single inlined body. Zero selects
// [DefaultMaxBodyBytes]; a negative value omits all bodies. Larger bodies
// are left out and the content/postData comment explains why.
MaxBodyBytes int
}
ExportOptions controls Export.
type Imported ¶
Imported is one flow parsed from a HAR document. Bodies are returned separately as decoded bytes so the caller can store them and fill in the BodyRef hashes; Flow.ID is 0 and is assigned by the caller.
func Import ¶
Import parses a HAR document into flows. It tolerates missing or mistyped fields, both literal and base64 bodies, and browser-specific extensions (Chrome's _initiator, _priority, _resourceType and friends are ignored). Bodies are returned decoded; the caller stores them and assigns IDs.
Timing is reconstructed from startedDateTime, time and the timings phases, so TTFB and totals survive a round trip. Header maps keep their Content-Encoding header even though the returned bytes are decoded; the BodyRef.Encoding field is left empty to reflect what the caller stores.
type Log ¶
type Log struct {
Version string `json:"version"`
Creator Creator `json:"creator"`
Browser *Creator `json:"browser,omitempty"`
Pages []Page `json:"pages,omitempty"`
Entries []Entry `json:"entries"`
Comment string `json:"comment,omitempty"`
}
Log is the HAR 1.2 log object.
type NVP ¶
type NVP struct {
Name string `json:"name"`
Value string `json:"value"`
Comment string `json:"comment,omitempty"`
}
NVP is a name/value pair used for headers and query parameters.
type Page ¶
type Page struct {
StartedDateTime string `json:"startedDateTime"`
ID string `json:"id"`
Title string `json:"title"`
PageTimings PageTimings `json:"pageTimings"`
Comment string `json:"comment,omitempty"`
}
Page is a browser page; pano never writes pages but tolerates them on import.
type PageTimings ¶
type PageTimings struct {
OnContentLoad float64 `json:"onContentLoad,omitempty"`
OnLoad float64 `json:"onLoad,omitempty"`
Comment string `json:"comment,omitempty"`
}
PageTimings holds page load milestones in milliseconds.
type PanoExt ¶
type PanoExt struct {
ID flow.ID `json:"id"`
Short string `json:"short"`
Kind flow.Kind `json:"kind"`
State flow.State `json:"state,omitempty"`
Session string `json:"session,omitempty"`
Error string `json:"error,omitempty"`
Tags []string `json:"tags,omitempty"`
Rules []flow.RuleHit `json:"rules,omitempty"`
ReqTruncated bool `json:"reqTruncated,omitempty"`
RespTruncated bool `json:"respTruncated,omitempty"`
Replay bool `json:"replay,omitempty"`
ReplayOf flow.ID `json:"replayOf,omitempty"`
}
PanoExt is the per-entry "_pano" extension object.
type Param ¶
type Param struct {
Name string `json:"name"`
Value string `json:"value,omitempty"`
FileName string `json:"fileName,omitempty"`
ContentType string `json:"contentType,omitempty"`
Comment string `json:"comment,omitempty"`
}
Param is one posted form parameter.
type PostData ¶
type PostData struct {
MimeType string `json:"mimeType"`
Params []Param `json:"params,omitempty"`
Text string `json:"text,omitempty"`
Encoding string `json:"encoding,omitempty"`
Comment string `json:"comment,omitempty"`
}
PostData is a request body. Encoding is a pano extension (HAR 1.2 has no base64 flag for request bodies): it is "base64" when Text is not UTF-8 text.
type Redactor ¶
type Redactor struct {
// Headers returns a redacted copy of h. It must not modify h.
Headers func(http.Header) http.Header
// Text returns a redacted copy of a text body.
Text func(string) string
}
Redactor masks secrets in header values and text bodies. Either function may be nil; a nil *Redactor disables redaction entirely.
type Request ¶
type Request struct {
Method string `json:"method"`
URL string `json:"url"`
HTTPVersion string `json:"httpVersion"`
Cookies []Cookie `json:"cookies"`
Headers []NVP `json:"headers"`
QueryString []NVP `json:"queryString"`
PostData *PostData `json:"postData,omitempty"`
HeadersSize int64 `json:"headersSize"`
BodySize int64 `json:"bodySize"`
Comment string `json:"comment,omitempty"`
}
Request is the request half of an entry.
type Response ¶
type Response struct {
Status int `json:"status"`
StatusText string `json:"statusText"`
HTTPVersion string `json:"httpVersion"`
Cookies []Cookie `json:"cookies"`
Headers []NVP `json:"headers"`
Content Content `json:"content"`
RedirectURL string `json:"redirectURL"`
HeadersSize int64 `json:"headersSize"`
BodySize int64 `json:"bodySize"`
Comment string `json:"comment,omitempty"`
// Error is Chrome's "_error" extension (e.g. "net::ERR_CONNECTION_RESET").
// pano never writes it but uses it on import when no "_pano" is present.
Error string `json:"_error,omitempty"`
}
Response is the response half of an entry.
type Timings ¶
type Timings struct {
Blocked float64 `json:"blocked"`
DNS float64 `json:"dns"`
Connect float64 `json:"connect"`
Send float64 `json:"send"`
Wait float64 `json:"wait"`
Receive float64 `json:"receive"`
SSL float64 `json:"ssl"`
Comment string `json:"comment,omitempty"`
}
Timings breaks the entry down by phase, in milliseconds. -1 marks a phase that does not apply or was not measured.