Current API middleware implementations have very low test coverage and contain tightly coupled logic that makes testing, debugging, and maintenance difficult. In particular, validation and error handling paths include complex async flows, repeated schema compilation, and limited observability during request processing.
Proposed Changes
- Validator Caching (Performance Improvement)
Avoid recompiling AJV validators for every request.
class ValidatorCache {
private cache = new Map();
async getValidator(path, method) {
const key = `${path}:${method}`;
if (!this.cache.has(key)) {
this.cache.set(key, await this.compileValidator(path, method));
}
return this.cache.get(key);
}
}
- Simplified Validation Middleware Flow :
async function validationMiddleware(options) {
return async (req, res, next) => {
try {
sanitizeInput(req.body);
const validate =
await validatorCache.getValidator(options.path, options.method);
if (!validate(req.body)) {
throw new ProblemException({ status: 422 });
}
await validateDocuments(req, options);
next();
} catch (err) {
next(err);
}
};
}
- Problem Middleware Error Handling
Helper utilities
function extractErrorType(type: string): string {
return type.replace('https://api.asyncapi.com/problem/', '');
}
function categorizeError(status: number): 'client' | 'server' {
return status >= 500 ? 'server' : 'client';
}
So the simplified middleware flow:
function problemMiddleware(error, req, res, next) {
if (res.headersSent) {
return next(error);
}
try {
const problemShape = error.get();
const status = problemShape.status || 500;
problemShape.status = status;
problemShape.title ||= 'Internal server error';
const errorType = extractErrorType(problemShape.type);
const category = categorizeError(status);
logger.error(
`[${req.method}] ${req.path} >> Status:: ${status}, Type:: ${errorType}`,
{ category }
);
const problem = error.toObject({
includeStack: status >= 500,
includeCause: status >= 500,
});
res.status(status).json(problem);
} catch (err) {
next(err);
}
}
Steps to Reproduce:
npx nyc npm test
npx nyc report --reporter=html
start coverage/index.html
- Navigate to
problem.middleware.js, validation.middleware.js
Happy to raise a PR for this if the maintainers approve
Current API middleware implementations have very low test coverage and contain tightly coupled logic that makes testing, debugging, and maintenance difficult. In particular, validation and error handling paths include complex async flows, repeated schema compilation, and limited observability during request processing.
Proposed Changes
Avoid recompiling AJV validators for every request.
Helper utilities
So the simplified middleware flow:
Steps to Reproduce:
npx nyc npm testnpx nyc report --reporter=htmlstart coverage/index.htmlproblem.middleware.js,validation.middleware.jsHappy to raise a PR for this if the maintainers approve