如何将参数传递给 express.js 路由器?

26

这是从Express.js的路由指南中修改过的示例:

var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
  res.send('Birds home page');
});

router.get('/about', function(req, res) {
  res.send('About birds');
});

...
app.use('/birds', router);
app.use('/fish', router);

当我访问/birds/about/fish/about时,这将打印出"关于鸟类"。

如何向路由程序传递参数或其他内容,以便在控制器函数中可以区分这两个不同的路由?

例如,当访问/birds/about时,我想看到"鸟儿会飞",当访问/fish/about时,我想看到"鱼儿会游泳"。

理想情况下,我希望能够传递一些"配置对象",这样小型应用程序就不需要知道它可能被挂载到的所有可能路由(伪代码):

    router.get('/about', function(req, res) {
      res.send(magic_configuration.about_text);
    });
   ....
   magically_set_config(router, {about_text: "Bears eat fish"})
   app.use('/bears', router);

router.ge('/birds/about',...) 的例子是什么? - David Haim
@DavidHaim:我有一组相关的路由(一个“迷你应用程序”)。我希望能够重复使用它们,而不是复制它们,否则,如果我添加另一个路由,我将不得不为/birds/fish都复制更改,这样很容易出错。 - Sergey
5个回答

44

这是我想到的:通过将“迷你应用配置”分配给req来传递:

app.use('/birds', function (req, res, next) {
    req.animal_config = {
        name: 'Bird',
        says: 'chirp'
    };
    next();
}, animal_router);

app.use('/cats', function (req, res, next) {
    req.animal_config = {
        name: 'Cat',
        says: 'meow'
    }
    next();        
}, animal_router);

然后在我的路由中,我可以访问它们:

var express = require('express');
var router = express.Router();

...

router.get('/about', function(req, res) {
  var animal = req.animal_config;
  res.send(animal.name + ' says ' + animal.says);
});

这种方法允许在不修改应用程序代码的情况下,在另一个位置轻松挂载“迷你应用程序”,并提供不同的配置:

app.use('/bears', function (req, res, next) {
    req.animal_config = {
        name: 'Bear',
        says: 'rawr'
    };
    next();
}, animal_router);

1
一个微型中间件 :) 非常高效,可以将例如数据库连接传递给不值得使用MVC开销的路由处理程序。 - flaschbier
@flaschbier 很抱歉又翻出这个话题。我正在考虑是采用微型中间件方式还是将我的值设置为环境变量(由进程设置而不是全局设置)。使用环境变量可以使我的代码更清晰,但我从来不喜欢使用它们。在这两种方法之间有什么建议吗?它只用于传递字符串(或将JSON作为字符串传递)。我知道除此之外的任何内容都不起作用,因为环境变量只能是字符串。 - Felipe
2
@Felipe - 云基础设施使用环境来编排服务。因此,我认为在应用程序中使用环境来注入全局参数没有问题。但是,不应滥用它来在应用程序的不同部分之间传递信息(破坏软件结构),但当它是外部配置,并且设计上在服务器进程的生命周期内不会更改时,通过环境注入它没有问题。 - flaschbier

15

你基本上是在讨论向路由器注入配置的问题。

我曾遇到类似的问题,发现理论上你可以导出一个接受配置并返回已创建和配置好的路由器的函数,而不是导出路由器本身。

因此,在您的情况下,调用代码将如下所示:

var animal_router = require('./animal_router')

app.use('/birds', animal_router({
    name: 'Bird',
    says: 'chirp'
}));

app.use('/cats', animal_router({
    name: 'Cat',
    says: 'meow'
}));

虽然./animal_router.js看起来可能是这样的:

var express = require('express');

// Create wrapper function that will adjust router based on provided configuration
var wrapper = function (animal_config) {
    var router = express.Router();
    
    router.get('/about', function(req, res) {
        var animal = animal_config;
        res.send(animal.name + ' says ' + animal.says);
    });

    return router;
}

module.exports = wrapper;

10

因此,如果您想通过URL提供更改,则可以像这样注入参数:

router.get('/:animal/about', function(req, res) {
    // here we have bird or fish in req.params.animal
    if(req.params.animal == 'bird') {
        res.send('Birds can fly');
    } else if(req.params.animal == 'fish') {
        res.send('Fish can swim');
    } else {
        res.send('Unknown animal');
    }
});
app.use('/', router);

1
是的,我考虑过了,但它也会匹配“/dinosaurs/about”。我想避免这种情况。 - Sergey
在未知动物情况下,您可以简单地调用next()。这样,任何其他匹配的路由都有机会被调用。 - Andrew Lavers

2

-1

您可以这样添加路由参数:

router.get('/about/:param1/:param2', function(req, res) {
 //then you can call this handler  through /about/1/sometext get these params from request object:
  console.log(req.params.param1, req.params.param2); // 1, 'sometext'
  res.send('About birds');
});

或者您可以通过查询参数发送参数:

router.get('/about', function(req, res) {
 //then you can call this handler  through /about?param1=1&param2=sometext get these params from request object as well:
  console.log(req.query.param1, req.query.param2); // 1, 'sometext'
  res.send('About birds');
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接