Last active
October 20, 2022 17:45
-
-
Save RascalTwo/351e9f81cd04a5c27fa43c7db6c14480 to your computer and use it in GitHub Desktop.
This file contains 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
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