feat(proxy): add capture_headers config and user_id to canonical request log#24
Conversation
…est log Add log.capture_headers config option that captures specified request headers as structured log attributes on the canonical request entry, strips them before forwarding upstream, and enforces safety constraints (max 10, no sensitive headers, 256-char truncation). Also log the proxy auth username as user_id in the canonical request log line and OTel span attributes.
- Guard capture header stripping against injected credentials (prevents misconfiguration from deleting injected credential headers) - Use rune-safe truncation for captured header values (avoids splitting multi-byte UTF-8 characters at the 256-byte boundary) - Add duplicate header name validation at startup - Add CONNECT/TLS intercept path tests for capture_headers stripping, credential preservation, and user_id propagation - Improve test readability (fmt.Sprintf for header generation)
📦 Previous Review (superseded by newer review)Claude finished @andybons's task in 3m 4s —— View job Code Review
SummaryThe feature is well-structured. The separation between pre-injection headers (snapshotted for logging) and post-injection headers (forwarded upstream) is handled correctly in both the HTTP and CONNECT paths. The injected-credential bypass logic ( Two issues worth addressing before merge: Issues1.
|
…brary safety Address PR review: SetCaptureHeaders now validates against sensitive headers, max count, and duplicates — protecting direct library callers who bypass YAML config parsing. Also use utf8.ValidString to avoid allocation during truncation.
📦 Previous Review (superseded by newer review)Claude finished @andybons's task in 3m 3s —— View job Code Review
SummaryBoth fixes from the previous review round are correctly implemented. The sensitive-header blocklist is now enforced canonically in the proxy package, and the One issue from the prior review remains open. Remaining Issue
|
Ensures capture_headers values appear in logs for denied requests and 502 errors in the CONNECT/TLS interception path. ErrorHandler retrieves headers from context (set by Rewrite); policy denial and credential error paths clone req.Header directly since Rewrite hasn't run yet.
|
Fixed the remaining issue in facdb80:
|
📦 Previous Review (superseded by newer review)Claude finished @andybons's task in 2m 16s —— View job Code Review
SummaryAll three issues from the previous two review rounds are correctly fixed. The feature is ready to merge. Previous issues — all resolved:
The pre-injection header snapshot strategy is correct throughout: The injected-credential bypass guard ( One nitRedundant double validation in
// Can remove this block:
if err := validateCaptureHeaders(cfg.Log.CaptureHeaders); err != nil {
return nil, err
}Not a bug, and the early fail-fast has minor value, so fine to leave or clean up at discretion. Acknowledged gap (low-impact, pre-existing)
|
…estHeaders gaps - Remove duplicate validateCaptureHeaders call in New() since SetCaptureHeaders already validates - Remove the validateCaptureHeaders wrapper (tests call proxy.ValidateCaptureHeaders directly) - Add RequestHeaders to handleHTTP credential-error log path
|
Claude finished @andybons's task in 3m 23s —— View job Code Review
SummaryAll issues from prior review rounds are fully resolved. The feature is ready to merge. Previously open items — all closed:
Review of new code in the final two commits:
Auth / user_id flow:
Capture header stripping: The Security: The No new issues found. |
Adds log.capture_headers config and user_id to the canonical request log line. See commit messages for details.