使用 Express.js 嵌套路由器休息

假设我想让 REST 端点看起来大致如下:

/user/
/user/user_id


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

如果有意义的话,对每一个进行 CRUD。例如,/user POST 创建一个新用户,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将 URL 传递给 userRouter,但是使用更具体的 /user/*user_id*/items/路由器传递给 itemRouter 呢?另外,如果可能的话,我希望 itemRouter 也可以访问 user _ id。

129231 次浏览

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

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

你可以通过将路由器作为 中间件附加到其他路由器上来嵌套路由器,不管有没有 params

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

mergeParams快车 4.5.0推出(2014年7月5日)

在本例中,itemRouter附加到 /:userId/items路由上的 userRouter

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

- > hello user
- > hello user 5
- > hello items from user 5
- > 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);
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"}

可控的嵌套路线。

我想要一个具体的例子,做嵌套的路线在一个非常可管理的方式在快递4,这是顶部搜索结果“嵌套的路线在快递”。例如,这里有一个 API,它有许多需要分解的路由。

./index.js:

var app = require('express')();


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


app.listen(3000);

./path/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;

./path/api/products s.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”在目录默认的 Web 页面中的工作方式,那么这将很容易基于递归来扩展您的组织,而不需要将入口点更改为代码。“ index.js”是在目录中使用 要求时访问的默认文档。

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 问题,但是它本身很适合封装关注点。

仅供参考,最近我进入了动作英雄领域,发现它有全功能的 w/socket 和任务,更像是一个真正的框架一体化,完全颠覆了 REST 范式。你应该去看看裸体快递。

使用@Jason Sebring 解决方案,并适应 Typecript。

服务器

import Routes from './api/routes';
app.use('/api/', Routes);

/api/path/index.ts

import { Router } from 'express';
import HomeRoutes from './home';


const router = Router();


router.use('/', HomeRoutes);
// add other routes...


export default router;

API/路线/家庭

import { Request, Response, Router } from 'express';


const router = Router();


router.get('/', (req: Request, res: Response) => {
res.json({
message: 'Welcome to API',
});
});


export default router;

尝试添加 { mergeParams: true }看看简单的例子,它的中间件使用它在控制器文件 getUser同样为 postUser

const userRouter = require("express").Router({ mergeParams: true });
export default ()=>{
userRouter
.route("/")
.get(getUser)
.post(postUser);


userRouter.route("/:user_id").get(function () {});
}

本着 Express 模块化路由器的精神,我们应该为用户和项目提供一个单独的路由器。那个路由器不是我们顶级应用程序逻辑的一部分。我们可以把它嵌入到用户的路由器中。

用户路由器

const users = require('express').Router();
const items = require('./items');


//...


// Our root route to /users
albums.get('/', function(req, res, next) {
// res.send() our response here
});


// A route to handle requests to any individual user, identified by an user id
users.get('/:userId', function(req, res, next) {
let userId = req.params.userId;
// retrieve user from database using userId
// res.send() response with user data
});


// Note, this route represents /users/:userId/items because our top-level router is already forwarding /users to our Users router!
users.use('/:userId/items', items);


//...


module.exports = users;

项目路由器

// We need to merge params to make userId available in our Items router
const items = require('express').Router({ mergeParams: true });


//...


// The root router for requests to our items path
items.get('/', function(req, res, next) {
let userId = req.params.userId; // Here is where mergeParams makes its magic


// retrieve user's track data and render items list page
});


// The route for handling a request to a specific item
items.get('/:itemId', function(req, res, next) {
let userId = req.params.userId; // <-- mergeParams magic
let itemId = req.params.itemId;


// retrieve individual item data and render on single item page
});


//...


module.exports = items;

来源

Express 路由器(Express.Router ())使参数保持分离,因此您必须显式地告诉 Express 合并这些参数。 例如: Expres.Router ({ mergeParams: true })

//以上行是对您问题的回答。