rest与Express.js嵌套路由器

假设我想让REST端点看起来像这样:

/user/ /user/user_id /user/user_id/items/ /user/user_id/items/item_id 

每个CRUD都是有道理的。 例如,/ user POST创build一个新用户,GET获取所有用户。 / user / user_id GET只提取一个用户。

项目是用户特定的,所以我把它们放在user_id下,这是一个特定的用户。

现在要使Express路由模块化,我做了几个路由器实例。 有一个用户的路由器,并为该项目的路由器。

 var userRouter = require('express').Router(); userRouter.route('/') .get(function() {}) .post(function() {}) userRouter.route('/:user_id') .get(function() {}) var itemRouter = require('express').Router(); itemRouter.route('/') .get(function() {}) .post(function() {}) itemRouter.route('/:item_id') .get(function() {}) app.use('/users', userRouter); // Now how to add the next router? // app.use('/users/', itemRouter); 

item的URL是user的URL分层结构的后代。 现在我怎么得到/users到userRouter的URL,但更具体的路线/user/*user_id*/items/到itemRouter? 而且,如果可能的话,我还希望user_id可以被itemRouter访问。

您可以通过将路由器附加为其他路由器上的中间件来嵌套路由器,使用或不使用params

如果要从父路由器访问params ,则必须将{mergeParams: true}传递给子路由器。

mergeParams在Express 4.5.0 (2014年7月5日)

在这个例子中, itemRouter被连接到/:userId/items路由上的userRouter

这将导致以下可能的路线:

GET /user – > hello user
GET /user/5 – > hello user 5
GET /user/5/items – > hello items from user 5
GET /user/5/items/6 – > hello item 6 from user 5

 var express = require('express'); var app = express(); var userRouter = express.Router(); // you need to set mergeParams: true on the router, // if you want to access params from the parent router var itemRouter = express.Router({mergeParams: true}); // you can nest routers by attaching them as middleware: userRouter.use('/:userId/items', itemRouter); userRouter.route('/') .get(function (req, res) { res.status(200) .send('hello users'); }); userRouter.route('/:userId') .get(function (req, res) { res.status(200) .send('hello user ' + req.params.userId); }); itemRouter.route('/') .get(function (req, res) { res.status(200) .send('hello items from user ' + req.params.userId); }); itemRouter.route('/:itemId') .get(function (req, res) { res.status(200) .send('hello item ' + req.params.itemId + ' from user ' + req.params.userId); }); app.use('/user', userRouter); app.listen(3003); 

可pipe理的嵌套路线…

我想要一个具体的例子,在express 4中以一种非常易于pipe理的方式进行嵌套路由,这是“express in express nested routes”的最高search结果。 这里有一个API可能会有很多路线需要分解。

./index.js:

 var app = require('express')(); // anything beginning with "/api" will go into this app.use('/api', require('./routes/api')); app.listen(3000); 

./routes/api/index.js:

 var router = require('express').Router(); // split up route handling router.use('/products', require('./products')); router.use('/categories', require('./categories')); // etc. module.exports = router; 

./routes/api/products.js:

 var router = require('express').Router(); // api/products router.get('/', function(req, res) { res.json({ products: [] }); }); // api/products/:id router.get('/:id', function(req, res) { res.json({ id: req.params.id }); }); module.exports = router; 

在文件夹结构中嵌套示例

我注意到了一些关于“嵌套文件夹结构”的评论。 这是隐含的,但不是很明显,所以我添加了下面的部分。 以下是路由嵌套文件夹结构的具体示例。

 index.js /api index.js /admin index.js /users index.js list.js /permissions index.js list.js 

这更多的是节点工作原理的一个例子。 如果您在文件夹中使用“index.js”,类似于“index.html”在网页中如何在默认目录下工作,这将很容易通过recursion来扩展您的组织,而无需将您的入口点更改为代码。 “index.js”是在目录中使用require时访问的默认文档。

index.js的内容

 const express = require('express'); const router = express.Router(); router.use('/api', require('./api')); module.exports = router; 

/api/index.js的内容

 const express = require('express'); const router = express.Router(); router.use('/admin', require('./admin')); module.exports = router; 

/api/admin/index.js的内容

 const express = require('express'); const router = express.Router(); router.use('/users', require('./users')); router.use('/permissions', require('./permissions')); module.exports = router; 

/api/admin/users/index.js的内容

 const express = require('express'); const router = express.Router(); router.get('/', require('./list')); module.exports = router; 

这里可能有一些DRY问题,但是它确实适合于关注问题。

 var userRouter = require('express').Router(); var itemRouter = require('express').Router({ mergeParams: true }); userRouter.route('/') .get(function(req, res) {}) .post(function(req, res) {}) userRouter.route('/:user_id') .get(function() {}) itemRouter.route('/') .get(function(req, res) {}) .post(function(req, res) {}) itemRouter.route('/:item_id') .get(function(req, res) { return res.send(req.params); }); app.use('/user/', userRouter); app.use('/user/:user_id/item', itemRouter); 

你问题的第二部分的关键是使用mergeParams选项

 var itemRouter = require('express').Router({ mergeParams: true }); 

/user/jordan/item/cat我得到一个回应:

 {"user_id":"jordan","item_id":"cat"} 

你只需要一个路由器,像这样使用它:

 router.get('/users'); router.get('/users/:user_id'); router.get('/users/:user_id/items'); router.get('/users/:user_id/items/:item_id'); app.use('api/v1', router);