winston-middleware 0.2.3 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +8 -1
- package/AUTHORS +4 -1
- package/LICENSE +1 -1
- package/Readme.md +94 -25
- package/index.js +115 -29
- package/package.json +64 -10
- package/test/test.js +637 -361
package/test/test.js
CHANGED
|
@@ -1,384 +1,660 @@
|
|
|
1
|
-
var
|
|
2
|
-
var assert = require('assert');
|
|
3
|
-
var winston = require('winston');
|
|
4
|
-
var expressWinston = require('../index');
|
|
1
|
+
var should = require('should');
|
|
5
2
|
var util = require('util');
|
|
6
|
-
var
|
|
3
|
+
var _ = require('underscore');
|
|
4
|
+
|
|
5
|
+
var mocks = require('node-mocks-http');
|
|
6
|
+
var winston = require('winston');
|
|
7
|
+
|
|
8
|
+
var expressWinston = require('../index.js');
|
|
9
|
+
|
|
10
|
+
expressWinston.ignoredRoutes.push('/ignored');
|
|
11
|
+
expressWinston.responseWhitelist.push('body');
|
|
12
|
+
|
|
13
|
+
expressWinston.bodyBlacklist.push('potato');
|
|
14
|
+
|
|
15
|
+
var MockTransport = function (test, options) {
|
|
16
|
+
test.transportInvoked = false;
|
|
7
17
|
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
winston.Transport.call(this, options || {});
|
|
19
|
+
|
|
20
|
+
this.log = function (level, msg, meta, cb) {
|
|
21
|
+
test.transportInvoked = true;
|
|
22
|
+
test.log.level = level;
|
|
23
|
+
test.log.msg = msg;
|
|
24
|
+
test.log.meta = meta;
|
|
25
|
+
this.emit('logged');
|
|
26
|
+
return cb();
|
|
27
|
+
};
|
|
10
28
|
};
|
|
11
29
|
util.inherits(MockTransport, winston.Transport);
|
|
12
30
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"an array with all the properties whitelisted in the body object": function(exports) {
|
|
25
|
-
assert.isArray(exports.bodyWhitelist);
|
|
26
|
-
},
|
|
27
|
-
"and the factory should contain a default request filter function": function(exports) {
|
|
28
|
-
assert.isFunction(exports.defaultRequestFilter);
|
|
31
|
+
var req = {};
|
|
32
|
+
var res = {};
|
|
33
|
+
|
|
34
|
+
var setUp = function (options) {
|
|
35
|
+
options = options || {};
|
|
36
|
+
|
|
37
|
+
var reqSpec = {
|
|
38
|
+
method: 'GET',
|
|
39
|
+
url: '/hello',
|
|
40
|
+
headers: {
|
|
41
|
+
'header-1': 'value 1'
|
|
29
42
|
},
|
|
30
|
-
|
|
31
|
-
|
|
43
|
+
query: {
|
|
44
|
+
val: '1'
|
|
32
45
|
},
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
params: {
|
|
47
|
+
id: 20
|
|
35
48
|
},
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (options.body) reqSpec.body = options.body;
|
|
52
|
+
|
|
53
|
+
if (options.ignoreRoute) reqSpec.url = '/ignored';
|
|
54
|
+
if (options.url) reqSpec.url = options.url;
|
|
55
|
+
|
|
56
|
+
req = mocks.createRequest(reqSpec);
|
|
57
|
+
|
|
58
|
+
req.route = {
|
|
59
|
+
path: reqSpec.url,
|
|
60
|
+
methods: {
|
|
61
|
+
get: true
|
|
38
62
|
}
|
|
39
|
-
}
|
|
40
|
-
}).export(module);
|
|
63
|
+
};
|
|
41
64
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
if (options.routePath) req.route.path = options.routePath;
|
|
66
|
+
|
|
67
|
+
res = mocks.createResponse();
|
|
68
|
+
res.status(200);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
describe('expressWinston', function () {
|
|
72
|
+
it('should contain an array with all the properties whitelisted in the req object', function () {
|
|
73
|
+
expressWinston.requestWhitelist.should.be.an.Array;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should contain an array with all the properties whitelisted in the res object', function () {
|
|
77
|
+
expressWinston.responseWhitelist.should.be.an.Array;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should contain an array for all the ignored routes', function () {
|
|
81
|
+
expressWinston.ignoredRoutes.should.be.an.Array;
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should contain an array with all the properties whitelisted in the body object', function () {
|
|
85
|
+
expressWinston.bodyWhitelist.should.be.an.Array;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should contain a default request filter function', function () {
|
|
89
|
+
expressWinston.defaultRequestFilter.should.be.a.Function;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should contain a default response filter function', function () {
|
|
93
|
+
expressWinston.defaultResponseFilter.should.be.a.Function;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should contain a default skip function', function () {
|
|
97
|
+
expressWinston.defaultSkip.should.be.a.Function;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should export a function for the creation of request logger middlewares', function () {
|
|
101
|
+
expressWinston.logger.should.be.a.Function;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('.errorLogger()', function () {
|
|
105
|
+
it('should be a function', function () {
|
|
106
|
+
expressWinston.errorLogger.should.be.a.Function;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should throw an error without options', function () {
|
|
110
|
+
(function () {
|
|
111
|
+
expressWinston.errorLogger();
|
|
112
|
+
}).should.throwError();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should throw an error without any transport specified', function () {
|
|
116
|
+
(function () {
|
|
117
|
+
expressWinston.errorLogger({});
|
|
118
|
+
}).should.throwError();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should throw an error with an empty list of transports', function () {
|
|
122
|
+
(function () {
|
|
123
|
+
expressWinston.errorLogger({
|
|
124
|
+
transports: []
|
|
76
125
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
var factory = expressWinston.errorLogger;
|
|
84
|
-
var callback = this.callback;
|
|
85
|
-
var req = {
|
|
86
|
-
url: "/hello?val=1",
|
|
87
|
-
headers: {
|
|
88
|
-
'header-1': 'value 1'
|
|
89
|
-
},
|
|
90
|
-
method: 'GET',
|
|
91
|
-
query: {
|
|
92
|
-
val: '1'
|
|
93
|
-
},
|
|
94
|
-
originalUrl: "/hello?val=1",
|
|
95
|
-
params: {
|
|
96
|
-
id: 20
|
|
97
|
-
},
|
|
98
|
-
nonWhitelistedProperty: "value that should not be logged"
|
|
99
|
-
};
|
|
100
|
-
var res = {
|
|
101
|
-
|
|
102
|
-
};
|
|
103
|
-
var originalError = new Error("This is the Error");
|
|
104
|
-
var test = {
|
|
105
|
-
req: req,
|
|
106
|
-
res: res,
|
|
107
|
-
log: {},
|
|
108
|
-
originalError: originalError,
|
|
109
|
-
pipelineError: null
|
|
110
|
-
};
|
|
111
|
-
var next = function(pipelineError) {
|
|
112
|
-
test.pipelineError = pipelineError;
|
|
113
|
-
return callback(null, test);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
var transport = new MockTransport({});
|
|
117
|
-
transport.log = function(level, msg, meta, cb) {
|
|
118
|
-
test.transportInvoked = true;
|
|
119
|
-
test.log.level = level;
|
|
120
|
-
test.log.msg = msg;
|
|
121
|
-
test.log.meta = meta;
|
|
122
|
-
this.emit('logged');
|
|
123
|
-
return cb();
|
|
124
|
-
};
|
|
125
|
-
var middleware = factory({
|
|
126
|
-
transports: [transport]
|
|
126
|
+
}).should.throwError();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should return a middleware function with four arguments that fit (err, req, res, next)', function () {
|
|
130
|
+
var middleware = expressWinston.errorLogger({
|
|
131
|
+
transports: [new MockTransport({})]
|
|
127
132
|
});
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
133
|
+
|
|
134
|
+
middleware.length.should.eql(4);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('errorLogger() middleware()', function () {
|
|
138
|
+
var result;
|
|
139
|
+
|
|
140
|
+
before(function (done) {
|
|
141
|
+
setUp();
|
|
142
|
+
|
|
143
|
+
var originalError = new Error('This is the Error');
|
|
144
|
+
|
|
145
|
+
var test = {
|
|
146
|
+
req: req,
|
|
147
|
+
res: res,
|
|
148
|
+
log: {},
|
|
149
|
+
originalError: originalError,
|
|
150
|
+
pipelineError: null
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
function next(pipelineError) {
|
|
154
|
+
test.pipelineError = pipelineError;
|
|
155
|
+
|
|
156
|
+
result = test;
|
|
157
|
+
|
|
158
|
+
return done();
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
var middleware = expressWinston.errorLogger({
|
|
162
|
+
transports: [new MockTransport(test)]
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
middleware(originalError, req, res, next);
|
|
145
166
|
});
|
|
146
|
-
assert.isUndefined(result.log.meta.req.nonWhitelistedProperty);
|
|
147
|
-
},
|
|
148
|
-
"the winston-middleware middleware should not swallow the pipeline error": function(result) {
|
|
149
|
-
assert.isNotNull(result.pipelineError);
|
|
150
|
-
assert.strictEqual(result.pipelineError, result.originalError);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}).export(module);
|
|
154
167
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
"with proper options": {
|
|
182
|
-
"the result should be a function with three arguments that fit req, res, next": function (factory) {
|
|
183
|
-
var middleware = factory({
|
|
184
|
-
transports: [
|
|
185
|
-
new MockTransport({
|
|
186
|
-
|
|
187
|
-
})
|
|
188
|
-
]
|
|
168
|
+
describe('encountering an error in the pipeline', function () {
|
|
169
|
+
it('should invoke the transport', function () {
|
|
170
|
+
result.transportInvoked.should.eql(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should find an error level of "error"', function () {
|
|
174
|
+
result.log.level.should.eql('error');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should find a message of "middlewareError"', function () {
|
|
178
|
+
result.log.msg.should.eql('middlewareError');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should contain a filtered request', function () {
|
|
182
|
+
result.log.meta.req.should.be.ok;
|
|
183
|
+
result.log.meta.req.method.should.eql('GET');
|
|
184
|
+
result.log.meta.req.query.should.eql({
|
|
185
|
+
val: '1'
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
result.log.meta.req.should.not.have.property('nonWhitelistedProperty');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('should not swallow the pipline error', function () {
|
|
192
|
+
result.pipelineError.should.be.ok;
|
|
193
|
+
result.pipelineError.should.eql(result.originalError);
|
|
189
194
|
});
|
|
190
|
-
assert.equal(middleware.length, 3);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
"When the winston-middleware middleware is invoked in pipeline": {
|
|
195
|
-
topic: function() {
|
|
196
|
-
var factory = expressWinston.logger;
|
|
197
|
-
var callback = this.callback;
|
|
198
|
-
var req = {
|
|
199
|
-
url: "/hello?val=1",
|
|
200
|
-
headers: {
|
|
201
|
-
'header-1': 'value 1'
|
|
202
|
-
},
|
|
203
|
-
method: 'GET',
|
|
204
|
-
query: {
|
|
205
|
-
val: '2'
|
|
206
|
-
},
|
|
207
|
-
originalUrl: "/hello?val=2",
|
|
208
|
-
params: {
|
|
209
|
-
id: 20
|
|
210
|
-
},
|
|
211
|
-
filteredProperty: "value that should not be logged"
|
|
212
|
-
};
|
|
213
|
-
var res = {
|
|
214
|
-
end: function(chunk, encoding) {}
|
|
215
|
-
};
|
|
216
|
-
var test = {
|
|
217
|
-
req: req,
|
|
218
|
-
res: res,
|
|
219
|
-
log: {}
|
|
220
|
-
};
|
|
221
|
-
var next = function(_req, _res, next) {
|
|
222
|
-
res.end();
|
|
223
|
-
return callback(null, test);
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
var transport = new MockTransport({});
|
|
227
|
-
transport.log = function(level, msg, meta, cb) {
|
|
228
|
-
test.transportInvoked = true;
|
|
229
|
-
test.log.level = level;
|
|
230
|
-
test.log.msg = msg;
|
|
231
|
-
test.log.meta = meta;
|
|
232
|
-
this.emit('logged');
|
|
233
|
-
return cb();
|
|
234
|
-
};
|
|
235
|
-
var middleware = factory({
|
|
236
|
-
transports: [transport]
|
|
237
195
|
});
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe('.logger()', function () {
|
|
200
|
+
it('should be a function', function () {
|
|
201
|
+
expressWinston.logger.should.be.a.Function;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('should throw an error without options', function () {
|
|
205
|
+
(function () {
|
|
206
|
+
expressWinston.logger();
|
|
207
|
+
}).should.throwError();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should throw an error without any transport specified', function () {
|
|
211
|
+
(function () {
|
|
212
|
+
expressWinston.logger({});
|
|
213
|
+
}).should.throwError();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should throw an error with an empty list of transports', function () {
|
|
217
|
+
(function () {
|
|
218
|
+
expressWinston.logger({
|
|
219
|
+
transports: []
|
|
220
|
+
});
|
|
221
|
+
}).should.throwError();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should throw an error if ignoreRoute option is not a function', function () {
|
|
225
|
+
(function () {
|
|
226
|
+
expressWinston.logger({
|
|
227
|
+
transports: [new MockTransport({})],
|
|
228
|
+
ignoreRoute: 'not a function'
|
|
229
|
+
});
|
|
230
|
+
}).should.throwError();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should return a middleware function with three arguments that fit (req, res, next)', function () {
|
|
234
|
+
var middleware = expressWinston.logger({
|
|
235
|
+
transports: [new MockTransport({})]
|
|
249
236
|
});
|
|
250
|
-
assert.isUndefined(result.log.meta.req.filteredProperty);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}).export(module);
|
|
254
237
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
238
|
+
middleware.length.should.eql(3);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe('logger() middleware()', function () {
|
|
242
|
+
describe('v0.1.x API', function () {
|
|
243
|
+
describe('when invoked on a route', function () {
|
|
244
|
+
var result;
|
|
245
|
+
|
|
246
|
+
before(function (done) {
|
|
247
|
+
setUp();
|
|
248
|
+
|
|
249
|
+
var test = {
|
|
250
|
+
req: req,
|
|
251
|
+
res: res,
|
|
252
|
+
log: {}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
function next(_req, _res, next) {
|
|
256
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
257
|
+
result = test;
|
|
258
|
+
return done();
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
var middleware = expressWinston.logger({
|
|
262
|
+
transports: [new MockTransport(test)]
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
middleware(req, res, next);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('should invoke the transport', function () {
|
|
269
|
+
result.transportInvoked.should.eql(true);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should contain a filtered request', function () {
|
|
273
|
+
result.log.meta.req.should.be.ok;
|
|
274
|
+
result.log.meta.req.method.should.eql('GET');
|
|
275
|
+
result.log.meta.req.query.should.eql({
|
|
276
|
+
val: '1'
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
result.log.meta.req.should.not.have.property('nonWhitelistedProperty');
|
|
280
|
+
});
|
|
289
281
|
});
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
282
|
+
|
|
283
|
+
describe('when invoked on a route that should be ignored', function () {
|
|
284
|
+
var result;
|
|
285
|
+
|
|
286
|
+
before(function (done) {
|
|
287
|
+
setUp({
|
|
288
|
+
ignoreRoute: true
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
var test = {
|
|
292
|
+
req: req,
|
|
293
|
+
res: res,
|
|
294
|
+
log: {}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
function next(_req, _res, next) {
|
|
298
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
299
|
+
result = test;
|
|
300
|
+
return done();
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
var middleware = expressWinston.logger({
|
|
304
|
+
transports: [new MockTransport(test)]
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
middleware(req, res, next);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('should not invoke the transport', function () {
|
|
311
|
+
result.transportInvoked.should.eql(false);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('should contain a filtered request', function () {
|
|
315
|
+
result.log.should.be.empty;
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
describe('v0.2.x API', function () {
|
|
321
|
+
describe('when invoked on a route', function () {
|
|
322
|
+
var result;
|
|
323
|
+
|
|
324
|
+
before(function (done) {
|
|
325
|
+
setUp({
|
|
326
|
+
body: {
|
|
327
|
+
username: "bobby",
|
|
328
|
+
password: "top-secret",
|
|
329
|
+
age: 42,
|
|
330
|
+
potato: 'Russet'
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
req.routeLevelAddedProperty = 'value that should be logged';
|
|
335
|
+
|
|
336
|
+
res.nonWhitelistedProperty = 'value that should not be logged';
|
|
337
|
+
res.routeLevelAddedProperty = 'value that should be logged';
|
|
338
|
+
|
|
339
|
+
var test = {
|
|
340
|
+
req: req,
|
|
341
|
+
res: res,
|
|
342
|
+
log: {}
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
function next(_req, _res, next) {
|
|
346
|
+
req._startTime = (new Date) - 125;
|
|
347
|
+
|
|
348
|
+
req._routeWhitelists.req = ['routeLevelAddedProperty'];
|
|
349
|
+
req._routeWhitelists.res = ['routeLevelAddedProperty'];
|
|
350
|
+
|
|
351
|
+
req._routeWhitelists.body = ['username'];
|
|
352
|
+
req._routeBlacklists.body = ['age'];
|
|
353
|
+
|
|
354
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
355
|
+
|
|
356
|
+
result = test;
|
|
357
|
+
|
|
358
|
+
return done();
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
var middleware = expressWinston.logger({
|
|
362
|
+
transports: [new MockTransport(test)]
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
middleware(req, res, next);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('should invoke the transport', function () {
|
|
369
|
+
result.transportInvoked.should.eql(true);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('should contain a filtered request', function () {
|
|
373
|
+
result.log.meta.req.should.be.ok;
|
|
374
|
+
result.log.meta.req.method.should.eql('GET');
|
|
375
|
+
result.log.meta.req.query.should.eql({
|
|
376
|
+
val: '1'
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
result.log.meta.req.body.should.not.have.property('age');
|
|
380
|
+
result.log.meta.req.body.should.not.have.property('potato');
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('should contain a filtered response', function () {
|
|
384
|
+
result.log.meta.res.should.be.ok;
|
|
385
|
+
|
|
386
|
+
result.log.meta.res.statusCode.should.eql(200);
|
|
387
|
+
result.log.meta.res.routeLevelAddedProperty.should.be.ok;
|
|
388
|
+
|
|
389
|
+
result.log.meta.res.should.not.have.property('nonWhitelistedProperty');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should contain a response time', function () {
|
|
393
|
+
result.log.meta.responseTime.should.be.within(120, 130);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
describe('when invoked on a route with an empty response body', function () {
|
|
398
|
+
var result;
|
|
399
|
+
|
|
400
|
+
before(function (done) {
|
|
401
|
+
setUp({
|
|
402
|
+
url: '/hello',
|
|
403
|
+
body: {}
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
req.routeLevelAddedProperty = 'value that should be logged';
|
|
407
|
+
|
|
408
|
+
var test = {
|
|
409
|
+
req: req,
|
|
410
|
+
res: res,
|
|
411
|
+
log: {}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
function next(_req, _res, next) {
|
|
415
|
+
res.end();
|
|
416
|
+
|
|
417
|
+
result = test;
|
|
418
|
+
|
|
419
|
+
return done();
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
var middleware = expressWinston.logger({
|
|
423
|
+
transports: [new MockTransport(test)]
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
middleware(req, res, next);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
it('should not have an empty body in meta.req', function () {
|
|
430
|
+
result.log.meta.res.should.not.have.property('body');
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe('when invoked on a route with transport level of "error"', function () {
|
|
435
|
+
var result;
|
|
436
|
+
|
|
437
|
+
before(function (done) {
|
|
438
|
+
setUp({
|
|
439
|
+
url: "/hello",
|
|
440
|
+
body: {}
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
req.routeLevelAddedProperty = 'value that should be logged';
|
|
444
|
+
|
|
445
|
+
res.nonWhitelistedProperty = 'value that should not be logged';
|
|
446
|
+
res.routeLevelAddedProperty = 'value that should be logged';
|
|
447
|
+
|
|
448
|
+
var test = {
|
|
449
|
+
req: req,
|
|
450
|
+
res: res,
|
|
451
|
+
log: {}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
function next(_req, _res, next) {
|
|
455
|
+
req._routeWhitelists.req = ['routeLevelAddedProperty'];
|
|
456
|
+
req._routeWhitelists.res = ['routeLevelAddedProperty'];
|
|
457
|
+
|
|
458
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
459
|
+
result = test;
|
|
460
|
+
return done();
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
var middleware = expressWinston.logger({
|
|
464
|
+
transports: [new MockTransport(test, {
|
|
465
|
+
level: 'error'
|
|
466
|
+
})],
|
|
467
|
+
statusLevels: true
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
middleware(req, res, next);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
it('should not invoke the transport', function () {
|
|
474
|
+
result.transportInvoked.should.eql(false);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
describe('when invoked on a route that should be ignored (options.ignoreRoute)', function () {
|
|
479
|
+
var result;
|
|
480
|
+
|
|
481
|
+
before(function (done) {
|
|
482
|
+
setUp({
|
|
483
|
+
url: '/is-not-logged'
|
|
484
|
+
});
|
|
485
|
+
req.skip = true;
|
|
486
|
+
var test = {
|
|
487
|
+
req: req,
|
|
488
|
+
res: res,
|
|
489
|
+
log: {}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
function next(_req, _res, next) {
|
|
493
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
494
|
+
result = test;
|
|
495
|
+
return done();
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
var middleware = expressWinston.logger({
|
|
499
|
+
transports: [new MockTransport(test)],
|
|
500
|
+
ignoreRoute: function (req, res) {
|
|
501
|
+
return req.skip === true && req.url.match(/^\/is-not-log/);
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
middleware(req, res, next);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
it('should not invoke the transport', function () {
|
|
509
|
+
result.transportInvoked.should.eql(false);
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
it('should contain a filtered request', function () {
|
|
513
|
+
result.log.should.be.empty;
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
describe('log.msg', function () {
|
|
519
|
+
var result;
|
|
520
|
+
|
|
521
|
+
function logMsgSetup(url, msg, expressFormat, done) {
|
|
522
|
+
setUp({
|
|
523
|
+
url: url || '/an-url'
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
var test = {
|
|
527
|
+
req: req,
|
|
528
|
+
res: res,
|
|
529
|
+
log: {}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
function next(_req, _res, next) {
|
|
533
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
534
|
+
|
|
535
|
+
result = test;
|
|
536
|
+
|
|
537
|
+
return done();
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
var loggerOptions = {
|
|
541
|
+
transports: [new MockTransport(test)]
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
if (msg) {
|
|
545
|
+
loggerOptions.msg = msg;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (expressFormat) {
|
|
549
|
+
delete loggerOptions.msg;
|
|
550
|
+
loggerOptions.expressFormat = true;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
var middleware = expressWinston.logger(loggerOptions);
|
|
554
|
+
|
|
555
|
+
middleware(req, res, next);
|
|
316
556
|
}
|
|
317
|
-
};
|
|
318
|
-
var res = {
|
|
319
|
-
statusCode: 200,
|
|
320
|
-
nonWhitelistedProperty: "value that should not be logged",
|
|
321
|
-
routeLevelAddedProperty: "value that should be logged",
|
|
322
|
-
end: function(chunk, encoding) {
|
|
323
557
|
|
|
558
|
+
describe('when default', function () {
|
|
559
|
+
|
|
560
|
+
before(function (done) {
|
|
561
|
+
logMsgSetup('/url-of-sandwich', null, false, done);
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
it('should match the custom format', function () {
|
|
565
|
+
result.log.msg.should.eql('HTTP GET /url-of-sandwich');
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
describe('using Express format', function () {
|
|
570
|
+
before(function (done) {
|
|
571
|
+
logMsgSetup('/all-the-things', null, true, done);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it('should match the Express format', function () {
|
|
575
|
+
var resultMsg = result.log.msg;
|
|
576
|
+
resultMsg.should.startWith('\u001b[90mGET /all-the-things\u001b[39m \u001b[32m200\u001b[39m \u001b[90m');
|
|
577
|
+
resultMsg.should.endWith('ms\u001b[39m');
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
describe('when customized', function () {
|
|
582
|
+
before(function (done) {
|
|
583
|
+
logMsgSetup('/all-the-things', 'Foo {{ req.method }} {{ req.url }}', false, done);
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
it('should match the custom format', function () {
|
|
587
|
+
result.log.msg.should.eql('Foo GET /all-the-things');
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
describe('log.skip', function () {
|
|
593
|
+
var result;
|
|
594
|
+
|
|
595
|
+
function logSkipSetup(url, skip, done) {
|
|
596
|
+
setUp({
|
|
597
|
+
url: url || '/an-url'
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
var test = {
|
|
601
|
+
req: req,
|
|
602
|
+
res: res,
|
|
603
|
+
log: {}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
function next(_req, _res, next) {
|
|
607
|
+
res.end('{ "message": "Hi! I\'m a chunk!" }');
|
|
608
|
+
|
|
609
|
+
result = test;
|
|
610
|
+
|
|
611
|
+
return done();
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
var loggerOptions = {
|
|
615
|
+
transports: [new MockTransport(test)]
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
if (skip) {
|
|
619
|
+
loggerOptions.skip = skip;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
var middleware = expressWinston.logger(loggerOptions);
|
|
623
|
+
|
|
624
|
+
middleware(req, res, next);
|
|
324
625
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
626
|
+
|
|
627
|
+
describe('when default', function () {
|
|
628
|
+
|
|
629
|
+
before(function (done) {
|
|
630
|
+
logSkipSetup('/url-of-sandwich', null, done);
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
it('should be logged', function () {
|
|
634
|
+
result.log.msg.should.eql('HTTP GET /url-of-sandwich');
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
describe('when using custom function returning true', function () {
|
|
639
|
+
before(function (done) {
|
|
640
|
+
logSkipSetup('/url-of-sandwich', function(req, res) { return req.url.indexOf('sandwich') != -1 }, done);
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
it('should not be logged', function () {
|
|
644
|
+
should.not.exist(result.log.msg);
|
|
645
|
+
});
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
describe('when using custom function returning false', function () {
|
|
649
|
+
before(function (done) {
|
|
650
|
+
logSkipSetup('/hello', function(req, res) { return req.url.indexOf('sandwich') != -1 }, done);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
it('should be logged', function () {
|
|
654
|
+
result.log.msg.should.eql('HTTP GET /hello');
|
|
655
|
+
});
|
|
656
|
+
});
|
|
352
657
|
});
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
assert.isTrue(result.transportInvoked);
|
|
357
|
-
}
|
|
358
|
-
, "the meta should contain a filtered request": function(result){
|
|
359
|
-
assert.isTrue(!!result.log.meta.req, "req should be defined in meta");
|
|
360
|
-
assert.isNotNull(result.log.meta.req);
|
|
361
|
-
assert.equal(result.log.meta.req.method, "GET");
|
|
362
|
-
assert.deepEqual(result.log.meta.req.query, { val: '2' });
|
|
363
|
-
assert.isUndefined(result.log.meta.req.nonWhitelistedProperty);
|
|
364
|
-
|
|
365
|
-
assert.isNotNull(result.log.meta.req.routeLevelAddedProperty);
|
|
366
|
-
}
|
|
367
|
-
, "the meta should contain a filtered request body": function(result) {
|
|
368
|
-
assert.deepEqual(result.log.meta.req.body, {username: 'bobby'});
|
|
369
|
-
assert.isUndefined(result.log.meta.req.body.password);
|
|
370
|
-
}
|
|
371
|
-
, "the meta should contain a filtered response": function(result){
|
|
372
|
-
assert.isTrue(!!result.log.meta.res, "res should be defined in meta");
|
|
373
|
-
assert.isNotNull(result.log.meta.res);
|
|
374
|
-
assert.equal(result.log.meta.res.statusCode, 200);
|
|
375
|
-
assert.isNotNull(result.log.meta.res.routeLevelAddedProperty);
|
|
376
|
-
}
|
|
377
|
-
, "the meta should contain a response time": function(result){
|
|
378
|
-
assert.isTrue(!!result.log.meta.responseTime, "responseTime should be defined in meta");
|
|
379
|
-
assert.isNotNull(result.log.meta.responseTime);
|
|
380
|
-
assert.isTrue(result.log.meta.responseTime > 120);
|
|
381
|
-
assert.isTrue(result.log.meta.responseTime < 130);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}).export(module);
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
});
|