middleware.js
4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
var request = require('supertest')
, express = require('express')
, http = require('http')
, errors = require('..')
, assert = require('assert');
var explanation = 'The X API Key provided is invalid or expired'
, response = 'Specify a valid X-API-Key header and retry the request'
, message = 'Invalid X API Key'
, theError = new errors.Http401Error(message, explanation, response);
function createServer(port, errorHandler) {
var app = exports.app = express();
app.set('port', port);
app.use(function(req, res, next) {
if (req instanceof Error) {
return next(err);
}
if (req.get('X-API-Key') == 'abc123') {
return next();
}
throw theError;
});
app.use(errorHandler);
app.use(app.router);
app.get('/echo/:msg', function(req, res) {
res.send(req.params.msg);
});
return app;
}
function validate(app, includeStack, connectCompat, title) {
var stackStr = includeStack ? "stack " : "no stack";
var testName = "html includes title, "
+ (connectCompat ? "fewer " : "more ")
+ "details "
+ "and " + stackStr;
it(testName, function(done) {
request(app)
.get('/echo/hi')
.set('Accept', 'text/html')
.set('X-API-Key', 'abc1234')
.expect('Content-Type', /html/)
.expect(401)
.end(function(err, res) {
if (err) {
done(err);
}
res.text.should.include(title);
if (includeStack) {
res.text.should.include('id=\"stacktrace\"');
}
if (!connectCompat) {
res.text.should.include(explanation);
res.text.should.include(response);
}
res.text.should.include(message);
done();
});
});
testName = "text should contain message and " + stackStr;
it(testName, function(done) {
request(app)
.get('/echo/hi')
.set('Accept', 'text/plain')
.set('X-API-Key', 'abc1234')
.expect('Content-Type', /text/)
.expect(401)
.end(function(err, res) {
if (err) {
done(err);
}
res.text.should.include(message);
if (includeStack) {
res.text.should.include('at ');
}
done();
});
});
testName = "json should contain full values and " + stackStr;
it(testName, function(done) {
request(app)
.get('/echo/hi')
.set('Accept', 'application/json')
.set('X-API-Key', 'abc1234')
.expect('Content-Type', /json/)
.expect(401)
.end(function(err, res) {
if (err) {
done(err);
}
var json = {error: theError.toJSON()};
if (includeStack) {
json.error.stack = theError.stack;
}
assert.deepEqual(JSON.parse(res.text), json);
done();
});
});
};
//connect middleware - works fine, but not as pretty
//due to the nature of the custom toString() on our errors
express.errorHandler.title = 'Out Of The Box Connect';
var app = createServer(3942, express.errorHandler());
describe('Connect errorHandler()', function() {
validate(app, true, false, express.errorHandler.title);
});
// errors middleware in connect compat mode
// looks just like a vanilla connect.errorHandler response
app = createServer(3943, errors.errorHandler({connectCompat: true, title: 'Connect Compat'}));
describe('Errors errorHandler() in compat mode', function() {
validate(app, true, true, 'Connect Compat');
});
// errors flavor middleware - preferred
// contains complete custom error details
app = createServer(3944, errors.errorHandler({title: 'Errors Middleware'}));
describe('Errors errorHandler() in non compat mode', function() {
validate(app, false, false, 'Errors Middleware');
});
//errors flavor middleware - preferred
//contains complete custom error details + stack
app = createServer(3944, errors.errorHandler({title: 'Errors Middleware', includeStack: true}));
describe('Errors errorHandler() in non compat mode + stack', function() {
validate(app, true, false, 'Errors Middleware');
});