@@ -72,28 +72,6 @@ func Middleware(logger LoggerInterface) echo.MiddlewareFunc {
7272 entry .Data .APIKeyHash = hashAPIKey (authHeader )
7373 }
7474
75- // Log request headers if enabled
76- if cfg .LogHeaders {
77- entry .Data .RequestHeaders = extractHeaders (req .Header )
78- }
79-
80- // Capture request body if enabled
81- if cfg .LogBodies && req .Body != nil {
82- if snapshot := core .GetRequestSnapshot (req .Context ()); snapshot != nil {
83- body := snapshot .CapturedBody ()
84- switch {
85- case snapshot .BodyNotCaptured :
86- entry .Data .RequestBodyTooBigToHandle = true
87- case body != nil :
88- captureLoggedRequestBody (entry , body )
89- default :
90- captureRequestBodyForLogging (entry , req )
91- }
92- } else {
93- captureRequestBodyForLogging (entry , req )
94- }
95- }
96-
9775 // Store entry in context for potential enrichment by handlers
9876 c .Set (string (LogEntryKey ), entry )
9977
@@ -104,7 +82,7 @@ func Middleware(logger LoggerInterface) echo.MiddlewareFunc {
10482 ResponseWriter : c .Response (),
10583 body : & bytes.Buffer {},
10684 shouldCapture : func () bool {
107- return shouldCaptureResponseBody (c )
85+ return auditEnabledForContext ( c . Request (). Context ()) && shouldCaptureResponseBody (c )
10886 },
10987 }
11088 c .SetResponse (responseCapture )
@@ -115,16 +93,24 @@ func Middleware(logger LoggerInterface) echo.MiddlewareFunc {
11593
11694 applyExecutionPlan (entry , c .Request ().Context ())
11795
96+ if ! auditEnabledForContext (c .Request ().Context ()) {
97+ return err
98+ }
99+
118100 // Calculate duration
119101 entry .DurationNs = time .Since (start ).Nanoseconds ()
120102
121103 // ResolveResponseStatus applies Echo v5 precedence rules for committed responses,
122104 // suggested status codes, and errors implementing HTTPStatusCoder.
123105 _ , entry .StatusCode = echo .ResolveResponseStatus (c .Response (), err )
124106
107+ // Request capture is deferred until after next so a later-resolved
108+ // Audit=false plan can skip it entirely.
109+ PopulateRequestData (entry , req , cfg )
110+
125111 // Log response headers if enabled
126112 if cfg .LogHeaders {
127- entry . Data . ResponseHeaders = extractHeaders ( c .Response ().Header ())
113+ PopulateResponseHeaders ( entry , c .Response ().Header ())
128114 }
129115
130116 // Capture response body if enabled
@@ -205,35 +191,6 @@ func enrichEntryWithExecutionPlan(entry *LogEntry, plan *core.ExecutionPlan) {
205191 }
206192}
207193
208- func captureRequestBodyForLogging (entry * LogEntry , req * http.Request ) {
209- if req .ContentLength > MaxBodyCapture {
210- entry .Data .RequestBodyTooBigToHandle = true
211- return
212- }
213-
214- // Read up to MaxBodyCapture+1 to detect overflow safely.
215- // Uses io.LimitReader to enforce the cap regardless of
216- // Content-Length (handles chunked/unknown-length requests).
217- limitedReader := io .LimitReader (req .Body , MaxBodyCapture + 1 )
218- bodyBytes , err := io .ReadAll (limitedReader )
219- if err != nil {
220- return
221- }
222- if int64 (len (bodyBytes )) > MaxBodyCapture {
223- entry .Data .RequestBodyTooBigToHandle = true
224- // Reconstruct full body for downstream: read bytes + unread remainder
225- origBody := req .Body
226- req .Body = & combinedReadCloser {
227- Reader : io .MultiReader (bytes .NewReader (bodyBytes ), origBody ),
228- rc : origBody ,
229- }
230- return
231- }
232-
233- captureLoggedRequestBody (entry , bodyBytes )
234- req .Body = io .NopCloser (bytes .NewBuffer (bodyBytes ))
235- }
236-
237194func captureLoggedRequestBody (entry * LogEntry , bodyBytes []byte ) {
238195 if len (bodyBytes ) == 0 {
239196 return
@@ -250,17 +207,6 @@ func captureLoggedRequestBody(entry *LogEntry, bodyBytes []byte) {
250207 entry .Data .RequestBody = toValidUTF8String (bodyBytes )
251208}
252209
253- // combinedReadCloser delegates Read to an io.Reader and Close to an io.ReadCloser.
254- // Used to reconstruct a request body that preserves the original closer.
255- type combinedReadCloser struct {
256- io.Reader
257- rc io.ReadCloser
258- }
259-
260- func (c * combinedReadCloser ) Close () error {
261- return c .rc .Close ()
262- }
263-
264210// responseBodyCapture wraps http.ResponseWriter to capture the response body.
265211// It implements http.Flusher and http.Hijacker by delegating to the underlying
266212// ResponseWriter if it supports those interfaces.
0 commit comments