app.param

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); ```