Skip to content

feat(middleware): intercept body-parse errors with structured logging - #306

Merged
Chucks1093 merged 1 commit into
accesslayerorg:mainfrom
ijeoma270:feat/issue-288
May 27, 2026
Merged

feat(middleware): intercept body-parse errors with structured logging#306
Chucks1093 merged 1 commit into
accesslayerorg:mainfrom
ijeoma270:feat/issue-288

Conversation

@ijeoma270

Copy link
Copy Markdown
Contributor

Fixes #288

What changed

  • New src/middlewares/body-parse-error.middleware.tsbodyParseErrorMiddleware error-handler that intercepts express.json() parse failures (SyntaxError with .body and entity.too.large) on mutation methods only (POST, PUT, PATCH, DELETE)
  • Emits logger.error with structured fields: type, method, path, requestId, clientIp, errorType — the raw request body and headers are never read or forwarded
  • Non-parse errors and non-mutation methods (GET, HEAD, OPTIONS) fall straight through to next(err)
  • src/app.ts — mounts the middleware immediately after express.json() so parse errors are caught before any route handler or the global error handler

Note: This middleware imports getClientIp from src/utils/client-ip.utils. That helper is introduced in PR #305 (issue #289). The client-ip.utils files are included here so this branch compiles independently; once #305 is merged the duplicate entry will resolve cleanly.

Why

Currently a malformed JSON body silently bubbles up to the global error handler and is logged with minimal context. Capturing parse failures at the source gives ops a structured, correlation-ID-linked log entry and returns a deterministic 400/413 to the client rather than a generic 500.

How to test

pnpm test src/middlewares/body-parse-error.middleware.test.ts

14 tests cover:

  • POST / PUT / PATCH / DELETE with invalid JSON → 400 + success: false
  • Raw body NOT present in the log entry
  • entity.too.large on a mutation method → 413
  • GET / HEAD with a SyntaxError → next(err) called, no log
  • Generic Error on a mutation method → passes through unchanged
  • ApiError (with statusCode) on a mutation method → passes through

…accesslayerorg#288)

Adds bodyParseErrorMiddleware to src/middlewares/body-parse-error.middleware.ts.

- Catches SyntaxError (malformed JSON) and entity.too.large errors produced
  by express.json() exclusively on mutation methods (POST, PUT, PATCH, DELETE)
- Emits a logger.error entry with: type, method, path, requestId, clientIp,
  errorType — raw request body and headers are never logged
- Returns 400 / 413 JSON to the client; non-parse errors and non-mutation
  methods pass straight through to next()
- Mounted in app.ts immediately after express.json() so parse errors are
  caught before any route or the global error handler sees them
- Depends on getClientIp from client-ip.utils (included here as a peer
  dependency; will resolve cleanly once accesslayerorg#289 is merged)
- 14 tests: all mutation verbs, GET/HEAD passthrough, generic errors,
  entity.too.large branch, no-body-in-log assertion, client response shape

Closes accesslayerorg#288
@Chucks1093
Chucks1093 merged commit abfaa5d into accesslayerorg:main May 27, 2026
1 check passed
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.

Add structured log for request body parse failure on mutation endpoints

2 participants