Skip to content

add BodyFn option to logger for request-body transforms - #47

Merged
umputun merged 3 commits into
masterfrom
feat/logger-bodyfn
Jul 16, 2026
Merged

add BodyFn option to logger for request-body transforms#47
umputun merged 3 commits into
masterfrom
feat/logger-bodyfn

Conversation

@umputun

@umputun umputun commented Jul 16, 2026

Copy link
Copy Markdown
Member

adds logger.BodyFn, a hook to transform the request body before it is logged, e.g. mask credentials, shrink or reformat a noisy body, or summarize it. Masking is the motivating case: a service that logs login requests shouldn't write plaintext passwords to its log.

this is dynamic, unlike masking a fixed set of known secret strings supplied ahead of time (lgr.Secret-style): the transform runs on the live request body, and what to change is the caller's decision, not the logger's. The logger only guarantees the result ends up on a single log line.

BodyFn

  • BodyFn(func(body string, truncated bool) string) Option, following the existing IPfn/UserFn/SubjFn precedent
  • runs only when body logging is on (WithBody) and the body is non-empty; a nil bodyFn keeps current behavior
  • gets the body (capped at MaxBodySize) plus a truncated flag, and owns the logged output. It decides how to render a truncated body, so the middleware imposes no placeholder and the transform doesn't have to assume JSON
  • read stays bounded by MaxBodySize, no full-body buffering

three logging fixes on the same path, found while building this

  • the single-line collapse only handled \n, so a lone \r (plus VT, FF, NEL, U+2028, U+2029) slipped through and a crafted body could forge extra log records. Now every line-break char is collapsed
  • the rendered log line went to Logf as the format string, so a % in a body or URL printed as %!s(MISSING). Now it is passed as an argument
  • formatApacheCombined emitted "METHOD URL" PROTO" instead of "METHOD URL PROTO". The protocol now stays inside the quoted request field

README updated, tests cover the new option and each fix.

umputun added 3 commits July 16, 2026 16:01
Add logger.BodyFn(func(body string, truncated bool) string) Option, a
transform applied to the request body before logging, e.g. to mask
credentials. It runs only when body logging is enabled (WithBody); the
transform receives the body capped at MaxBodySize plus a truncated flag
and fully owns the logged output, so it can emit a marker for a partial
body it can't safely process. The logger still collapses the result to a
single line to prevent log injection, and the read stays bounded by
MaxBodySize.
Two log-output defects on the body-logging path, surfaced while reviewing
the BodyFn change but predating it:

- the single-line collapse only neutralized LF; a lone CR (and VT, FF, NEL,
  U+2028, U+2029) survived, so a crafted body could forge extra log records.
  Collapse every line-break character before the whitespace-run pass.
- the rendered line was passed to Logf as the format string, so a '%' in a
  body or URL was interpreted as a format verb (e.g. %!s(MISSING)). Pass it
  as an argument instead.

Also add the missing nil-BodyFn default-path test plus CR/Unicode-separator
and percent-in-body regression tests.
Two review follow-ups on the logger:

- getBody no longer calls bodyFn for an empty request body - there is
  nothing to transform, and a transform returning a marker for empty input
  would otherwise log content for bodyless requests.
- formatApacheCombined closed the request quote after the URL, emitting
  "METHOD URL" PROTO" instead of the correct "METHOD URL PROTO". Move the
  space so the protocol stays inside the quoted request field, and fix the
  test that had asserted the malformed line.
Copilot AI review requested due to automatic review settings July 16, 2026 21:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 29537328224

Coverage remained the same at 96.21%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1293
Covered Lines: 1244
Line Coverage: 96.21%
Coverage Strength: 51.27 hits per line

💛 - Coveralls

@umputun
umputun merged commit ca9f902 into master Jul 16, 2026
4 checks passed
@umputun
umputun deleted the feat/logger-bodyfn branch July 16, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants