Documentation
¶
Overview ¶
Package check implements `cadish check`: it loads a Cadishfile (resolving `import` directives), then produces a per-site complexity report — the headline differentiator of cadish. The report estimates how expensive a config is to evaluate per request (regex evaluations, weighted cost, directive depth by lifecycle phase), flags dead/unreachable rules and unknown names, and offers optimization suggestions.
The cadishfile AST is semantics-free; every classification here (which phase a directive runs in, whether a matcher is a regex, whether a rule is dead) is applied by this package using its own directive catalog.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var PhaseOrder = []Phase{PhaseSetup, PhaseRECV, PhaseKEY, PhaseORIGIN, PhaseDELIVER}
PhaseOrder is the canonical display order for phases.
Functions ¶
func WriteJSONError ¶
WriteJSONError renders a top-level check failure (a root-file parse or read error, returned by Check before any Report exists) as a structured JSON object to w, so a `-json` consumer always receives valid, machine-readable JSON even when the config does not parse — instead of empty stdout. The shape mirrors a failed report: ok=false, one error diagnostic, no sites. path and strict are echoed so the JSON is self-describing and its outcome agrees with the (non-zero) exit code.
Types ¶
type CostBreakdown ¶
type CostBreakdown struct {
Exact int `json:"exact"`
Glob int `json:"glob"`
Regex int `json:"regex"`
}
CostBreakdown explains the estimated per-request cost: counts of evaluated predicates by weight class. Cost = Exact*1 + Glob*2 + Regex*10.
type Diagnostic ¶
type Diagnostic struct {
Severity Severity `json:"severity"`
// Position is "file:line:col" (empty file renders as "<input>").
Position string `json:"position"`
// Code is a short stable machine code, e.g. "unknown-directive".
Code string `json:"code"`
// Message is the human-readable explanation.
Message string `json:"message"`
// contains filtered or unexported fields
}
Diagnostic is a single finding tied to a source position.
type Phase ¶
type Phase string
Phase is a request-lifecycle phase. Directives are grouped by the phase in which they execute.
const ( // PhaseSetup is parse-once configuration (tls, cache, upstream, …); it does // not run per request. PhaseSetup Phase = "SETUP" // PhaseRECV is the request phase (respond, purge, route, pass). PhaseRECV Phase = "RECV" // PhaseKEY builds the cache key (cache_key). PhaseKEY Phase = "KEY" // PhaseORIGIN runs on a miss, against the origin response (cache_ttl, storage). PhaseORIGIN Phase = "ORIGIN" // PhaseDELIVER is the response phase (header, strip_cookies, cors). PhaseDELIVER Phase = "DELIVER" )
type Report ¶
type Report struct {
Path string `json:"path"`
// Diagnostics holds file-level findings not tied to a single site
// (e.g. import resolution failures).
Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
Sites []*SiteReport `json:"sites"`
}
Report is the full result of a check run.
func Check ¶
Check loads the Cadishfile at path, resolves its imports, and analyzes it into a complexity Report. A parse or read error on the *root* file is returned as err (a *cadishfile.ParseError or os error) so the caller can print a "file:line:col" diagnostic; all other findings — including import failures and per-site warnings — live in the returned Report.
func CheckSource ¶
CheckSource analyzes already-parsed source. filename is used for positions and for resolving imports relative to its directory. It is the in-memory analogue of Check, used in tests.
func CheckSourceSandboxed ¶
CheckSourceSandboxed is the sandboxed variant of CheckSource for use in the admin playground (/api/validate). It performs NO filesystem access: import directives are blocked (a clear diagnostic is emitted instead of reading the file) and geo/maxmind path probes are skipped. All non-filesystem diagnostics (unknown directives, arity errors, matcher issues, etc.) are still produced.
This prevents the admin endpoint from becoming an arbitrary host-file read primitive when an attacker submits a config containing `import /etc/passwd` or `geo { source maxmind /run/secrets/... }`.
func (*Report) Counts ¶
Counts returns the total number of error- and warning-severity diagnostics across the whole report.
func (*Report) ExitCode ¶
ExitCode is the process exit code: non-zero when there are errors, or — under strict — any warnings.
func (*Report) WriteJSON ¶
WriteJSON renders the report as indented JSON to w (for tooling). strict reflects whether the check ran under -strict, so the emitted JSON's outcome fields ("ok"/"strict") agree with the process exit code: under -strict a warnings-only report is a failure ("ok":false) even though "errors":0.
type Severity ¶
type Severity string
Severity classifies a diagnostic. Errors fail the check (non-zero exit); warnings only fail under -strict.
type SiteReport ¶
type SiteReport struct {
Addresses []string `json:"addresses"`
Position string `json:"position"`
// MatcherCount is the number of named matcher definitions in scope.
MatcherCount int `json:"matcher_count"`
// DirectiveCount is the total number of directives in scope.
DirectiveCount int `json:"directive_count"`
// RegexEvalsPerRequest is how many regex matchers (path_regex/host_regex/
// regex-valued header) a request evaluates on the hot path.
RegexEvalsPerRequest int `json:"regex_evals_per_request"`
// PhaseCounts is directive count grouped by lifecycle phase.
PhaseCounts map[Phase]int `json:"phase_counts"`
// EstimatedCost is the weighted per-request cost (see CostBreakdown).
EstimatedCost int `json:"estimated_cost"`
CostBreakdown CostBreakdown `json:"cost_breakdown"`
Suggestions []string `json:"suggestions,omitempty"`
Diagnostics []Diagnostic `json:"diagnostics,omitempty"`
}
SiteReport is the complexity report for one site (or the synthetic "(top-level)" scope for a bare imported fragment).