Skip to content

Commit

Permalink
Use module references when referencing exported properties.
Browse files Browse the repository at this point in the history
Fixes #92.

Allows user to override module-level whitelists and functions without
having to worry about using the right object reference.
  • Loading branch information
rosston committed Mar 9, 2016
1 parent 005bb1d commit 3b444e7
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 33 deletions.
55 changes: 22 additions & 33 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,42 @@ delete require.cache[require.resolve('underscore')];
* TODO: Include 'body' and get the defaultRequestFilter to filter the inner properties like 'password' or 'password_confirmation', etc. Pull requests anyone?
* @type {Array}
*/
var globalRequestWhitelist = ['url', 'headers', 'method', 'httpVersion', 'originalUrl', 'query'];
exports.requestWhitelist = ['url', 'headers', 'method', 'httpVersion', 'originalUrl', 'query'];

/**
* A default list of properties in the request body that are allowed to be logged.
* This will normally be empty here, since it should be done at the route level.
* @type {Array}
*/
var globalBodyWhitelist = [];
exports.bodyWhitelist = [];

/**
* A default list of properties in the request body that are not allowed to be logged.
* @type {Array}
*/
var globalBodyBlacklist = [];
exports.bodyBlacklist = [];

/**
* A default list of properties in the response object that are allowed to be logged.
* These properties will be safely included in the meta of the log.
* @type {Array}
*/
var globalResponseWhitelist = ['statusCode'];
exports.responseWhitelist = ['statusCode'];

/**
* A list of request routes that will be skipped instead of being logged. This would be useful if routes for health checks or pings would otherwise pollute
* your log files.
* @type {Array}
*/
var globalIgnoredRoutes = [];
exports.ignoredRoutes = [];

/**
* A default function to filter the properties of the req object.
* @param req
* @param propName
* @return {*}
*/
var defaultRequestFilter = function (req, propName) {
exports.defaultRequestFilter = function (req, propName) {
return req[propName];
};

Expand All @@ -79,15 +79,15 @@ var defaultRequestFilter = function (req, propName) {
* @param propName
* @return {*}
*/
var defaultResponseFilter = function (res, propName) {
exports.defaultResponseFilter = function (res, propName) {
return res[propName];
};

/**
* A default function to decide whether skip logging of particular request. Doesn't skip anything (i.e. log all requests).
* @return always false
*/
var defaultSkip = function() {
exports.defaultSkip = function() {
return false;
};

Expand All @@ -114,12 +114,12 @@ function filterObject(originalObj, whiteList, initialFilter) {
//


function errorLogger(options) {
exports.errorLogger = function errorLogger(options) {

ensureValidOptions(options);

options.requestWhitelist = options.requestWhitelist || globalRequestWhitelist;
options.requestFilter = options.requestFilter || defaultRequestFilter;
options.requestWhitelist = options.requestWhitelist || exports.requestWhitelist;
options.requestFilter = options.requestFilter || exports.defaultRequestFilter;
options.winstonInstance = options.winstonInstance || (new winston.Logger ({ transports: options.transports }));
options.msg = options.msg || 'middlewareError';
options.baseMeta = options.baseMeta || {};
Expand Down Expand Up @@ -149,26 +149,26 @@ function errorLogger(options) {

next(err);
};
}
};

//
// ### function logger(options)
// #### @options {Object} options to initialize the middleware.
//


function logger(options) {
exports.logger = function logger(options) {

ensureValidOptions(options);
ensureValidLoggerOptions(options);

options.requestWhitelist = options.requestWhitelist || globalRequestWhitelist;
options.bodyWhitelist = options.bodyWhitelist || globalBodyWhitelist;
options.bodyBlacklist = options.bodyBlacklist || globalBodyBlacklist;
options.responseWhitelist = options.responseWhitelist || globalResponseWhitelist;
options.requestFilter = options.requestFilter || defaultRequestFilter;
options.responseFilter = options.responseFilter || defaultResponseFilter;
options.ignoredRoutes = options.ignoredRoutes || globalIgnoredRoutes;
options.requestWhitelist = options.requestWhitelist || exports.requestWhitelist;
options.bodyWhitelist = options.bodyWhitelist || exports.bodyWhitelist;
options.bodyBlacklist = options.bodyBlacklist || exports.bodyBlacklist;
options.responseWhitelist = options.responseWhitelist || exports.responseWhitelist;
options.requestFilter = options.requestFilter || exports.defaultRequestFilter;
options.responseFilter = options.responseFilter || exports.defaultResponseFilter;
options.ignoredRoutes = options.ignoredRoutes || exports.ignoredRoutes;
options.winstonInstance = options.winstonInstance || (new winston.Logger ({ transports: options.transports }));
options.level = options.level || "info";
options.statusLevels = options.statusLevels || false;
Expand All @@ -178,7 +178,7 @@ function logger(options) {
options.colorStatus = options.colorStatus || false;
options.expressFormat = options.expressFormat || false;
options.ignoreRoute = options.ignoreRoute || function () { return false; };
options.skip = options.skip || defaultSkip;
options.skip = options.skip || exports.defaultSkip;

// Using mustache style templating
var template = _.template(options.msg, null, {
Expand Down Expand Up @@ -292,7 +292,7 @@ function logger(options) {

next();
};
}
};

function ensureValidOptions(options) {
if(!options) throw new Error("options are required by express-winston middleware");
Expand All @@ -305,14 +305,3 @@ function ensureValidLoggerOptions(options) {
throw new Error("`ignoreRoute` express-winston option should be a function");
}
}

module.exports.errorLogger = errorLogger;
module.exports.logger = logger;
module.exports.requestWhitelist = globalRequestWhitelist;
module.exports.bodyWhitelist = globalBodyWhitelist;
module.exports.bodyBlacklist = globalBodyBlacklist;
module.exports.responseWhitelist = globalResponseWhitelist;
module.exports.defaultRequestFilter = defaultRequestFilter;
module.exports.defaultResponseFilter = defaultResponseFilter;
module.exports.defaultSkip = defaultSkip;
module.exports.ignoredRoutes = globalIgnoredRoutes;
163 changes: 163 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,39 @@ describe('express-winston', function () {
middleware.length.should.eql(4);
});

it('should use the exported requestWhitelist', function() {
var originalWhitelist = expressWinston.requestWhitelist;
expressWinston.requestWhitelist = ['foo'];

var options = {
req: {foo: "bar"}
};
return errorLoggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.requestWhitelist = originalWhitelist;

result.log.meta.req.should.have.property('foo');
result.log.meta.req.should.not.have.property('url');
});
});

it('should use the exported defaultRequestFilter', function() {
var originalRequestFilter = expressWinston.defaultRequestFilter;
expressWinston.defaultRequestFilter = function() {
return 'foo';
};

var options = {
req: {foo: "bar"}
};
return errorLoggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.defaultRequestFilter = originalRequestFilter;

result.log.meta.req.url.should.equal('foo');
});
});

describe('when middleware function encounters an error in the pipeline', function () {
it('should invoke the transport', function () {
return errorLoggerTestHelper().then(function (result) {
Expand Down Expand Up @@ -299,6 +332,136 @@ describe('express-winston', function () {
});
});

it('should use the exported requestWhitelist', function() {
var originalWhitelist = expressWinston.requestWhitelist;
expressWinston.requestWhitelist = ['foo'];

var options = {
req: {foo: "bar"}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.requestWhitelist = originalWhitelist;

result.log.meta.req.should.have.property('foo');
result.log.meta.req.should.not.have.property('url');
});
});

it('should use the exported bodyWhitelist', function() {
var originalWhitelist = expressWinston.bodyWhitelist;
expressWinston.bodyWhitelist = ['foo'];

var options = {
req: {body: {foo: 'bar', baz: 'qux'}}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.bodyWhitelist = originalWhitelist;

result.log.meta.req.body.should.have.property('foo');
result.log.meta.req.body.should.not.have.property('baz');
});
});

it('should use the exported bodyBlacklist', function() {
var originalWhitelist = expressWinston.bodyBlacklist;
expressWinston.bodyBlacklist = ['foo'];

var options = {
req: {body: {foo: 'bar', baz: 'qux'}}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.bodyBlacklist = originalWhitelist;

result.log.meta.req.body.should.not.have.property('foo');
result.log.meta.req.body.should.have.property('baz');
});
});

it('should use the exported responseWhitelist', function() {
var originalWhitelist = expressWinston.responseWhitelist;
expressWinston.responseWhitelist = ['foo'];

var options = {
res: {foo: 'bar', baz: 'qux'}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.responseWhitelist = originalWhitelist;

result.log.meta.res.should.have.property('foo');
result.log.meta.res.should.not.have.property('baz');
});
});

it('should use the exported defaultRequestFilter', function() {
var originalRequestFilter = expressWinston.defaultRequestFilter;
expressWinston.defaultRequestFilter = function() {
return 'foo';
};

var options = {
req: {foo: "bar"}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.defaultRequestFilter = originalRequestFilter;

result.log.meta.req.url.should.equal('foo');
});
});

it('should use the exported defaultResponseFilter', function() {
var originalResponseFilter = expressWinston.defaultResponseFilter;
expressWinston.defaultResponseFilter = function() {
return 'foo';
};

var options = {
req: {foo: "bar"}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.defaultResponseFilter = originalResponseFilter;

result.log.meta.res.statusCode.should.equal('foo');
});
});

it('should use the exported defaultSkip', function() {
var originalSkip = expressWinston.defaultSkip;
expressWinston.defaultSkip = function() {
return true;
};

var options = {
req: {foo: "bar"}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.defaultSkip = originalSkip;

result.transportInvoked.should.eql(false);
});
});

it('should use the exported ignoredRoutes', function() {
var originalIgnoredRoutes = expressWinston.ignoredRoutes;
expressWinston.ignoredRoutes = ['/foo-route'];

var options = {
req: {url: '/foo-route'}
};
return loggerTestHelper(options).then(function (result) {
// Return to the original value for later tests
expressWinston.ignoredRoutes = originalIgnoredRoutes;

result.transportInvoked.should.eql(false);
});
});

describe('when middleware function is invoked on a route', function () {
function next(req, res, next) {
req._startTime = (new Date()) - 125;
Expand Down

0 comments on commit 3b444e7

Please sign in to comment.