feat: structured body-parse error log (#288) and client-IP extraction helper (#289) - #304
Closed
ijeoma270 wants to merge 1 commit into
Closed
feat: structured body-parse error log (#288) and client-IP extraction helper (#289)#304ijeoma270 wants to merge 1 commit into
ijeoma270 wants to merge 1 commit into
Conversation
Issue accesslayerorg#288 — src/middlewares/body-parse-error.middleware.ts - New error-handler middleware that intercepts body-parsing failures (SyntaxError with body, entity.too.large) exclusively on mutation methods (POST, PUT, PATCH, DELETE) - Emits logger.error with: type, method, path, requestId, clientIp, errorType — never logs the raw body or request headers - Returns 400 / 413 JSON to the client unchanged; non-parse errors and GET/HEAD/OPTIONS 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 - 14 tests covering: all mutation verbs, GET passthrough, generic errors, entity.too.large, no-body-in-log assertion, client response shape Issue accesslayerorg#289 — src/utils/client-ip.utils.ts - getClientIp(req, trusted?) reads the first IP from X-Forwarded-For when the socket address belongs to a trusted proxy (loopback, RFC-1918, IPv6 ULA); falls back to req.socket.remoteAddress otherwise - Accepts an optional predicate override for testing and custom deployments - Integrated into request-logger.middleware.ts (clientIp field in every request log entry) and body-parse-error.middleware.ts (clientIp in parse-failure logs) - 11 tests: trusted loopback/private ranges, array header, custom predicate, untrusted socket passthrough, missing socket edge cases Closes accesslayerorg#288 Closes accesslayerorg#289
|
@ijeoma270 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Contributor
Author
|
Closing in favour of separate PRs per issue. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #288
Closes #289
What changed
#288 — Structured log for request body parse failure (
src/middlewares/body-parse-error.middleware.ts)Added a dedicated Express error-handler middleware that intercepts body-parsing failures on mutation endpoints and emits a structured
error-level log before returning the client response.What is logged:
type: "body_parse_failure"methodandpath(endpoint path)requestId(for correlation with other log entries)clientIp(extracted via the trusted-proxy-aware helper from Add helper for extracting client IP from forwarded headers in request context #289)errorType:"invalid_json"or"entity.too.large"What is NOT logged:
Behaviour:
POST,PUT,PATCH,DELETE(mutation methods)GET,HEAD, and all non-parse errors pass through tonext()unchanged400for malformed JSON,413for oversized payloadsapp.tsimmediately afterexpress.json()— before routes and the global error handlerTests (14): all mutation verbs, GET passthrough, generic error passthrough, entity.too.large handling, assertion that body is absent from log, client response shape
#289 — Client IP extraction helper (
src/utils/client-ip.utils.ts)Added
getClientIp(req, trusted?)— a small, reusable helper that reads the real client IP fromX-Forwarded-Forwhen the socket comes from a trusted proxy, falling back to the direct socket address otherwise.Resolution order:
req.socket.remoteAddressis a trusted proxy (loopback, RFC-1918, IPv6 ULA), read the first (leftmost) IP fromX-Forwarded-ForTrust model:
trustedpredicate override for tests or custom deploymentsIntegration points:
request-logger.middleware.ts—clientIpfield added to every request log entrybody-parse-error.middleware.ts—clientIpincluded in parse-failure error logsTests (11): trusted loopback/private ranges, multi-hop
X-Forwarded-For, array-valued header, custom predicate, untrusted socket passthrough, missing socket edge casesHow to test