Skip to content

CXF-8228: Log the headers added to the HttpServletResponse - #3620

Open
ffang wants to merge 1 commit into
apache:mainfrom
ffang:CXF-8228
Open

ffang wants to merge 1 commit into
apache:mainfrom
ffang:CXF-8228

Conversation

@ffang

@ffang ffang commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

The logging feature only logged the headers in the protocol headers of the message, so headers added directly to the HttpServletResponse, by the application or by a servlet filter, were sent but not logged.

For server responses and faults, DefaultLogEventMapper now also logs the headers of the HttpServletResponse that are not in the protocol headers yet. Both sources have to be merged, because for responses without a body the event is created before the transport copies the protocol headers to the HttpServletResponse. Sensitive headers are masked as before.

The Servlet API is an optional dependency of the logging feature, and the code that uses it is in a separate class that is only used if the Servlet API is available.

The logging feature only logged the headers in the protocol headers of
the message, so headers added directly to the HttpServletResponse, by
the application or by a servlet filter, were sent but not logged.

For server responses and faults, DefaultLogEventMapper now also logs
the headers of the HttpServletResponse that are not in the protocol
headers yet. Both sources have to be merged, because for responses
without a body the event is created before the transport copies the
protocol headers to the HttpServletResponse. Sensitive headers are
masked as before.

The Servlet API is an optional dependency of the logging feature, and
the code that uses it is in a separate class that is only used if the
Servlet API is available.

@coheigea coheigea left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. A broken servlet response could fail the whole request. In HttpServletResponseHeaders.addHeaders, getHeaderNames() and getHeaders() are called without any guard. Logging should never break a request, but these calls can throw:
  • some wrapper or mock responses throw UnsupportedOperationException;
  • a response that was already recycled in async or continuation flows can throw too.

The caller is LoggingCallback.onClose, so an exception there aborts the response. Wrapping the loop in try { … } catch (RuntimeException e) { /* fall back to protocol headers */ } is cheap insurance.

  1. Hard-coded transport constants (minor). The new class repeats "HTTP.RESPONSE", "http.headers.copied" and "org.apache.cxf.http.add-headers" as strings. The comments explain why: cxf-rt-features-logging depends only on cxf-core. Two improvements:
  • Add a unit test or a @see link so renaming the constants in AbstractHTTPDestination or Headers can’t silently break this.
  • Alternatively, move the constants to Message or a core class.
  1. Multi-value headers are formatted differently depending on timing (cosmetic). Without add-headers, copyToResponse joins multiple values with a comma (setHeader("X", "a,b")).
  • After the copy (responses with a body), the log shows a,b.
  • Before the copy (no body), it shows [a, b].

It’s harmless, but it’s inconsistent.

  1. Nit: a class-loading error could still surface later. isServletApiAvailable catches LinkageError. That’s fine, but NoClassDefFoundError could still come up later, when HttpServletResponseHeaders is first loaded. It shouldn’t happen if the class check passed.

  2. Nit: header masking could be tidier. maskHeaders now streams the sensitive set once per header. That’s fine for realistic sizes. A lower-cased Set, or a TreeSet(CASE_INSENSITIVE_ORDER), would be tidier.

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.

2 participants