request-autopsy
v1.0.3
Published
Express middleware that auto-analyses every request and reports issues: wrong HTTP method, missing fields, security threats (XSS, SQLi, path traversal), performance problems, auth errors, oversized payloads, and more.
Maintainers
Readme
request-autopsy
Express middleware that auto-analyses every HTTP request/response pair and reports issues — wrong HTTP method, missing fields, security threats, performance problems, auth errors, oversized payloads, and more.
Zero dependencies. Pure Node.js built-ins only.
Install
npm install request-autopsyQuick Start
const express = require("express");
const requestAutopsy = require("request-autopsy");
const app = express();
app.use(express.json());
app.use(requestAutopsy()); // ← drop it in, done
app.post("/login", (req, res) => {
res.json({ success: true });
});
app.listen(3000);Every request will now print a full autopsy report to the console after it finishes.
Sample Output
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
💻 REQUEST AUTOPSY REPORT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔗 Endpoint : POST /login
🟡 Duration : 820ms
⚠️ Status : HTTP 400
🚧 Issues : 3
───────────────────────────────────────────
🟠 ERROR (2)
───────────────────────────────────────
[1] MISSING_FIELD
📌 Required field "password" is missing from request body
💡 Fix: Include "password" in the request body
[2] CLIENT_ERROR
📌 HTTP 400 client error
💡 Fix: Check request format, headers, and body against API documentation
🟡 WARNING (1)
───────────────────────────────────────
[1] SLOW_RESPONSE
📌 Response took 820ms — above acceptable threshold (>500ms)
💡 Fix: Optimize DB queries, add caching, or move work to background jobs
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━What It Detects
| # | Type | Severity | Description |
|---|------|----------|-------------|
| 1 | WRONG_METHOD | ERROR | e.g. GET sent to a POST-only route |
| 2 | UNKNOWN_ENDPOINT | WARN | Route not found in your registry |
| 3 | MISSING_FIELD | ERROR | Required body field is absent |
| 4 | EMPTY_FIELD | WARN | Field exists but is blank/whitespace |
| 5 | DUPLICATE_FIELD | WARN | Same key appears twice in JSON body |
| 6 | MISSING_CONTENT_TYPE | WARN | No Content-Type header on a body request |
| 7 | INVALID_CONTENT_TYPE | WARN | Unexpected Content-Type value |
| 8 | MISSING_AUTH | ERROR | Authorization header absent on protected route |
| 9 | INVALID_AUTH_FORMAT | WARN | Auth header not in Bearer <token> format |
| 10 | OVERSIZED_PAYLOAD | WARN | Body exceeds configured size limit |
| 11 | SLOW_RESPONSE | WARN | Response time > 500ms |
| 12 | CRITICAL_SLOW_RESPONSE | CRITICAL | Response time > 2000ms |
| 13 | SERVER_ERROR | CRITICAL | HTTP 5xx |
| 14 | NOT_FOUND | ERROR | HTTP 404 |
| 15 | METHOD_NOT_ALLOWED | ERROR | HTTP 405 |
| 16 | AUTH_ERROR | ERROR | HTTP 401 or 403 |
| 17 | VALIDATION_ERROR | ERROR | HTTP 422 |
| 18 | CLIENT_ERROR | ERROR | Other HTTP 4xx |
| 19 | XSS_ATTEMPT | CRITICAL | <script>, javascript:, onerror=, etc. |
| 20 | SQL_INJECTION_ATTEMPT | CRITICAL | OR '1'='1', UNION SELECT, DROP TABLE, etc. |
| 21 | PATH_TRAVERSAL_ATTEMPT | CRITICAL | ../../ in URL or body |
| 22 | SUSPICIOUS_HEADER | WARN | Malicious patterns in X-Forwarded-For, User-Agent, Referer |
| 23 | EXCESSIVE_FIELDS | WARN | More than 50 body fields (parameter pollution) |
| 24 | MISSING_QUERY_PARAM | WARN | Required query param absent |
Options
app.use(requestAutopsy({
// Register your routes — enables WRONG_METHOD and UNKNOWN_ENDPOINT detection
routes: [
{ path: "/login", methods: ["POST"] },
{ path: "/register", methods: ["POST"] },
{ path: "/users/:id", methods: ["GET", "PUT", "DELETE"] }
],
// Route prefixes that require an Authorization header
protectedRoutes: ["/api/", "/dashboard/"],
// Add or override required-field rules per endpoint
// Key format: "METHOD /path"
fieldRules: {
"POST /checkout": ["items", "total", "address"],
"PUT /profile": ["name", "email"]
},
// Required query parameters per path
requiredQueryParams: {
"/search": ["q"],
"/reports": ["from", "to"]
},
// Maximum allowed request body size (default: 1 MB)
maxPayloadBytes: 2 * 1024 * 1024,
// Output format: "pretty" | "json" | "both" | "silent"
output: "pretty",
// "all" logs every request; "issues-only" logs only requests with detected issues
logLevel: "issues-only",
// Custom callback — receives (issues[], ctx) after every request
onIssue: (issues, ctx) => {
if (issues.length > 0) {
myLogger.warn({ endpoint: ctx.endpoint, issues });
}
},
// Paths to skip entirely (default: /favicon.ico, /health, /healthz, /ping)
ignore: ["/health", "/metrics", "/favicon.ico"]
}));Output Modes
"pretty" (default)
Coloured, human-readable report in the terminal.
"json"
Machine-readable JSON — good for log aggregators (Datadog, ELK, etc.):
{
"timestamp": "2025-01-15T10:23:01.000Z",
"endpoint": "POST /login",
"method": "POST",
"statusCode": 400,
"duration": 95,
"issueCount": 2,
"healthy": false,
"issues": [
{
"severity": "ERROR",
"type": "MISSING_FIELD",
"issue": "Required field \"password\" is missing from request body",
"fix": "Include \"password\" in the request body"
}
]
}"both"
Prints both formats.
"silent"
Suppresses all console output — use onIssue to handle reports yourself.
Advanced: Custom Handler
app.use(requestAutopsy({
output: "silent",
onIssue: (issues, ctx) => {
const critical = issues.filter(i => i.severity === "CRITICAL");
if (critical.length > 0) {
alertingService.send({
endpoint: ctx.endpoint,
issues: critical
});
}
}
}));Named Exports (Advanced)
const {
analyzer, // core detection function
prettyReport, // pretty formatter
jsonReport // JSON formatter
} = require("request-autopsy");Built-in Required Fields
These endpoint → field mappings are detected automatically without any config:
| Endpoint | Required Fields |
|----------|----------------|
| POST /login | email, password |
| POST /register | name, email, password |
| POST /signup | name, email, password |
| POST /payment | amount, currency |
| POST /checkout | items, total |
| POST /reset-password | token, password |
| POST /verify-email | token |
| POST /refresh-token | refreshToken |
| PUT /profile | name |
| PUT /password | currentPassword, newPassword |
Override or extend with fieldRules option.
Author
Pramod Sithara Jayansiri
- GitHub: @PramodSithara
- npm: npmjs.com/pramodsithara
License
MIT © 2026 Pramod Sithara Jayansiri
