Skip to content

Instantly share code, notes, and snippets.

@RascalTwo
Last active October 20, 2022 17:45
Show Gist options
  • Save RascalTwo/351e9f81cd04a5c27fa43c7db6c14480 to your computer and use it in GitHub Desktop.
Save RascalTwo/351e9f81cd04a5c27fa43c7db6c14480 to your computer and use it in GitHub Desktop.
const util = require('util');
const debug = require('debug')('express-middleware-logger');
function deepIsEqual(one, two) {
if (one === two) return true;
if (typeof one !== typeof two) return false;
if (one === null || two === null) return false;
if (typeof one === 'object' && typeof two === 'object') return [...new Set([...Object.keys(one), ...Object.keys(two)])].every(key => deepIsEqual(one[key], two[key]));
return false;
}
function shallowCopyObject(obj, ignoredProperties = []) {
const copy = {};
for (const key in obj) {
if (!ignoredProperties.some(regex => regex.test(key))) copy[key] = obj[key];
}
return copy;
}
function objectDiffs(one, two) {
const diff = {};
for (const key of [...new Set([...Object.keys(one), ...Object.keys(two)])]) {
if (!deepIsEqual(one[key], two[key])) {
diff[key] = {
before: one[key],
after: two[key]
};
}
}
return diff;
}
module.exports = (app, { ignore: { properties = [], middlewares = [], callback = (request, middleware) => false } }) => {
const ignoredProperties = properties.map(r => new RegExp(r));
const ignoredMiddlewares = middlewares.map(r => new RegExp(r));
app._router.stack.forEach(middleware => {
const original = middleware.handle;
const { before, after } = (() => {
let originals = {};
let ignored = false;
return {
before(request, response, next) {
ignored = callback(request, middleware) || ignoredMiddlewares.some(regex => regex.test(middleware.name));
if (ignored) return next();
originals.request = shallowCopyObject(request, ignoredProperties);
originals.response = shallowCopyObject(response, ignoredProperties);
next();
},
after(error, request, response, next) {
if (ignored) return next(error);
const requestDiff = objectDiffs(originals.request, shallowCopyObject(request, ignoredProperties));
const responseDiff = objectDiffs(originals.response, shallowCopyObject(response, ignoredProperties));
if (!Object.keys(requestDiff).length && !Object.keys(responseDiff).length) return next(error);
if (Object.keys(requestDiff).length || Object.keys(responseDiff).length) debug(middleware.name);
if (Object.keys(requestDiff).length) debug(`request: ${Object.keys(requestDiff).reduce((string, key) => `${string}\n ${key}: ${util.inspect(requestDiff[key].before, { depth: 1, colors: true, }).replace(/\n/g, '\n ')} -> ${util.inspect(requestDiff[key].after, { depth: 1, colors: true, }).replace(/\n/g, '\n ')}`, '')}`);
if (Object.keys(responseDiff).length) debug(`response: ${Object.keys(responseDiff).reduce((string, key) => `${string}\n ${key}: ${util.inspect(responseDiff[key].before, { depth: 1, colors: true, }).replace(/\n/g, '\n ')} -> ${util.inspect(responseDiff[key].after, { depth: 1, colors: true, }).replace(/\n/g, '\n ')}`, '')}`);
next(error);
}
};
})();
middleware.handle = (request, response, next) => {
before(request, response, () =>
original(request, response, error =>
after(error, request, response, next)
)
);
};
});
};
/**
Example usage:
const app = express()
// add middlewares
require('./diffMiddleware')(app);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment