Skip to content

Commit 92ffbf5

Browse files
delvedorhekike
authored andcommitted
feat(router): add ignoreTrailingSlash router option (#1632)
1 parent d653625 commit 92ffbf5

File tree

5 files changed

+135
-3
lines changed

5 files changed

+135
-3
lines changed

lib/router.js

+6
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,18 @@ var ResourceNotFoundError = errors.ResourceNotFoundError;
3333
* @param {Boolean} [options.strictNext=false] - Throws error when next() is
3434
* called more than once, enabled onceNext option
3535
* @param {Object} [options.registry] - route registry
36+
* @param {Object} [options.ignoreTrailingSlash] - ignore trailing slash on
37+
* paths
3638
*/
3739
function Router(options) {
3840
assert.object(options, 'options');
3941
assert.object(options.log, 'options.log');
4042
assert.optionalBool(options.onceNext, 'options.onceNext');
4143
assert.optionalBool(options.strictNext, 'options.strictNext');
44+
assert.optionalBool(
45+
options.ignoreTrailingSlash,
46+
'options.ignoreTrailingSlash'
47+
);
4248

4349
EventEmitter.call(this);
4450

lib/routerRegistryRadix.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ var Chain = require('./chain');
99
*
1010
* @class RouterRegistryRadix
1111
* @public
12+
* @param {Object} options - an options object
13+
* @param {Object} [options.ignoreTrailingSlash] - ignore trailing slash on
14+
* paths
1215
*/
13-
function RouterRegistryRadix() {
14-
this._findMyWay = new FindMyWay();
16+
function RouterRegistryRadix(options) {
17+
this._findMyWay = new FindMyWay(options);
1518
this._routes = {};
1619
}
1720

test/router.test.js

+25
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,28 @@ test('toString()', function(t) {
346346
);
347347
t.end();
348348
});
349+
350+
test('toString() with ignoreTrailingSlash', function(t) {
351+
function handler(req, res, next) {
352+
res.send('Hello world');
353+
}
354+
355+
var router = new Router({
356+
log: {},
357+
ignoreTrailingSlash: true
358+
});
359+
router.mount({ method: 'GET', path: '/' }, [handler]);
360+
router.mount({ method: 'GET', path: '/a' }, [handler]);
361+
router.mount({ method: 'GET', path: '/a/b' }, [handler]);
362+
router.mount({ method: 'POST', path: '/' }, [handler]);
363+
364+
t.deepEqual(
365+
router.toString(),
366+
'└── / (GET|POST)\n' +
367+
' └── a (GET)\n' +
368+
' └── / (GET)\n' +
369+
' └── b (GET)\n' +
370+
' └── / (GET)\n'
371+
);
372+
t.end();
373+
});

test/routerRegistryRadix.test.js

+18
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,21 @@ test('toString()', function(t) {
9999
);
100100
t.end();
101101
});
102+
103+
test('toString() with ignoreTrailingSlash', function(t) {
104+
var registry = new RouterRegistryRadix({ ignoreTrailingSlash: true });
105+
registry.add(getTestRoute({ method: 'GET', path: '/' }));
106+
registry.add(getTestRoute({ method: 'GET', path: '/a' }));
107+
registry.add(getTestRoute({ method: 'GET', path: '/a/b' }));
108+
registry.add(getTestRoute({ method: 'POST', path: '/' }));
109+
110+
t.deepEqual(
111+
registry.toString(),
112+
'└── / (GET|POST)\n' +
113+
' └── a (GET)\n' +
114+
' └── / (GET)\n' +
115+
' └── b (GET)\n' +
116+
' └── / (GET)\n'
117+
);
118+
t.end();
119+
});

test/server.test.js

+81-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ before(function(cb) {
4646
dtrace: helper.dtrace,
4747
handleUncaughtExceptions: true,
4848
log: helper.getLog('server'),
49-
version: ['2.0.0', '0.5.4', '1.4.3']
49+
version: ['2.0.0', '0.5.4', '1.4.3'],
50+
ignoreTrailingSlash: true
5051
});
5152
SERVER.listen(PORT, '127.0.0.1', function() {
5253
PORT = SERVER.address().port;
@@ -159,6 +160,85 @@ test('get (path only)', function(t) {
159160
});
160161
});
161162

163+
test('get (path only - with trailing slash)', function(t) {
164+
SERVER.get('/foo/', function echoId(req, res, next) {
165+
res.send();
166+
next();
167+
});
168+
169+
var count = 0;
170+
171+
CLIENT.get('/foo/', function(err, _, res) {
172+
t.ifError(err);
173+
t.equal(res.statusCode, 200);
174+
175+
if (++count === 2) {
176+
t.end();
177+
}
178+
});
179+
180+
CLIENT.get('/foo', function(err, _, res) {
181+
t.ifError(err);
182+
t.equal(res.statusCode, 200);
183+
184+
if (++count === 2) {
185+
t.end();
186+
}
187+
});
188+
});
189+
190+
test('get (path only - with trailing slash and nested route)', function(t) {
191+
SERVER.get('/foo/', function echoId(req, res, next) {
192+
res.statusCode = 200;
193+
res.send();
194+
next();
195+
});
196+
197+
SERVER.get('/foo/bar', function echoId(req, res, next) {
198+
res.statusCode = 201;
199+
res.send();
200+
next();
201+
});
202+
203+
var count = 0;
204+
205+
CLIENT.get('/foo/', function(err, _, res) {
206+
t.ifError(err);
207+
t.equal(res.statusCode, 200);
208+
209+
if (++count === 4) {
210+
t.end();
211+
}
212+
});
213+
214+
CLIENT.get('/foo', function(err, _, res) {
215+
t.ifError(err);
216+
t.equal(res.statusCode, 200);
217+
218+
if (++count === 4) {
219+
t.end();
220+
}
221+
});
222+
223+
CLIENT.get('/foo/bar/', function(err, _, res) {
224+
t.ifError(err);
225+
t.equal(res.statusCode, 201);
226+
227+
if (++count === 4) {
228+
t.end();
229+
}
230+
});
231+
232+
CLIENT.get('/foo/bar', function(err, _, res) {
233+
t.ifError(err);
234+
t.equal(res.statusCode, 201);
235+
236+
if (++count === 4) {
237+
t.end();
238+
}
239+
});
240+
});
241+
162242
test('use + get (path only)', function(t) {
163243
SERVER.use(function(req, res, next) {
164244
next();

0 commit comments

Comments
 (0)