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