app.param([name], callback)
给路由参数添加回调触发器,这里的name
是参数名或者参数数组,function
是回调方法。回调方法的参数按序是请求对象,响应对象,下个中间件,参数值和参数名。
如果name
是数组,会按照各个参数在数组中被声明的顺序将回调触发器注册下来。还有,对于除了最后一个参数的其他参数,在他们的回调中调用next()
来调用下个声明参数的回调。对于最后一个参数,在回调中调用next()
将调用位于当前处理路由中的下一个中间件,如果name
只是一个string
那就和它是一样的(就是说只有一个参数,那么就是最后一个参数,和数组中最后一个参数是一样的)。
例如,当:user
出现在路由路径中,你可以映射用户加载的逻辑处理来自动提供req.user
给这个路由,或者对输入的参数进行验证。
app.param('user', function(req, res, next, id) {
User.find(id, function(error, user) {
if (err) {
next(err);
}
else if (user){
req.user = user;
} else {
next(new Error('failed to load user'));
}
});
});
对于Param
的回调定义的路由来说,他们是局部的。它们不会被挂载的app或者路由继承。所以,定义在app
上的Param
回调只有是在app
上的路由具有这个路由参数时才起作用。
在定义param
的路由上,param
回调都是第一个被调用的,它们在一个请求-响应循环中都会被调用一次并且只有一次,即使多个路由都匹配,如下面的例子:
app.param('id', function(req, res, next, id) {
console.log('CALLED ONLY ONCE');
next();
});
app.get('/user/:id', function(req, res, next) {
console.log('although this matches');
next();
});
app.get('/user/:id', function(req, res) {
console.log('and this mathces too');
res.end();
});
当GET /user/42
,得到下面的结果:
CALLED ONLY ONCE
although this matches
and this matches too
app.param(['id', 'page'], function(req, res, next, value) {
console.log('CALLED ONLY ONCE with', value);
next();
});
app.get('/user/:id/:page', function(req. res, next) {
console.log('although this matches');
next();
});
app.get('/user/:id/:page', function (req, res, next) {
console.log('and this matches too');
res.end();
});
当执行GET /user/42/3
,结果如下:
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this mathes too
下面章节描述的
app.param(callback)
在v4.11.0之后被弃用。
通过只传递一个回调参数给app.param(name, callback)
方法,app.param(naem, callback)
方法的行为将被完全改变。这个回调参数是关于app.param(name, callback)
该具有怎样的行为的一个自定义方法,这个方法必须接受两个参数并且返回一个中间件。
这个回调的第一个参数就是需要捕获的url的参数名,第二个参数可以是任一的JavaScript对象,其可能在实现返回一个中间件时被使用。
这个回调方法返回的中间件决定了当URL中包含这个参数时所采取的行为。
在下面的例子中,app.param(name, callback)
参数签名被修改成了app.param(name, accessId)
。替换接受一个参数名和回调,app.param()
现在接受一个参数名和一个数字。
var express = require('express');
var app = express();
app.param(function(param, option){
return function(req, res, next, val) {
if (val == option) {
next();
}
else {
res.sendStatus(403);
}
}
});
app.param('id', 1337);
app.get('/user/:id', function(req, res) {
res.send('Ok');
});
app.listen(3000, function() {
console.log('Ready');
});
在这个例子中,app.param(name, callback)
参数签名保持和原来一样,但是替换成了一个中间件,定义了一个自定义的数据类型检测方法来检测user id
的类型正确性。
app.param(function(param, validator) {
return function(req, res, next, val) {
if (validator(val)) {
next();
}
else {
res.sendStatus(403);
}
}
});
app.param('id', function(candidate) {
return !isNaN(parseFloat(candidate)) && isFinite(candidate);
});
在使用正则表达式来,不要使用
.
。例如,你不能使用/user-.+/
来捕获user-gami
,用使用[\\s\\S]
或者[\\w\\>W]
来代替(正如/user-[\\s\\S]+/
)。
//captures '1-a_6' but not '543-azser-sder'
router.get('/[0-9]+-[[\\w]]*', function);
//captures '1-a_6' and '543-az(ser"-sder' but not '5-a s'
router.get('/[0-9]+-[[\\S]]*', function);
//captures all (equivalent to '.*')
router.get('[[\\s\\S]]*', function);