使用Express.js嵌套路由器

hug*_*gie 126 javascript node.js express

假设我希望REST端点看起来像这样:

/user/
/user/user_id 

/user/user_id/items/
/user/user_id/items/item_id
Run Code Online (Sandbox Code Playgroud)

每个CRUD都有意义.例如,/ user POST创建一个新用户,GET将提取所有用户./ user/user_id GET只提取一个用户.

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

现在要制作快速路由模块我做了几个路由器实例.有一个用户路由器和一个路由器.

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);
Run Code Online (Sandbox Code Playgroud)

URL to item是URL层次结构的后代user.现在我如何获取/usersuserRouter的URL,但是更具体/user/*user_id*/items/的itemRouter 路由?而且,如果可能的话,我希望item_outer也可以访问user_id.

Wil*_*eer 244

您可以通过将路由器作为中间件附加到其他路由器上来嵌套路由器,无论是否有params.

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

mergeParamsExpress4.5.0中引入(2014年7月5日)

在这个例子中,itemRouter被附着在userRouter/:userId/items路线

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

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);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的回答.您在此处使用的路由器比Jordonias共享的路由器更明确地嵌套.但它在引擎盖下的工作方式是否相同?我想给你全面的赏金,但是几个小时之后我才能做到. (3认同)

Jas*_*ing 115

可管理的嵌套路线......

我想要一个在express 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);
Run Code Online (Sandbox Code Playgroud)

./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;
Run Code Online (Sandbox Code Playgroud)

./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;
Run Code Online (Sandbox Code Playgroud)

在文件夹结构中嵌套示例

我注意到一些关于"嵌套文件夹结构"的评论.它隐含在这里并不明显,所以我添加了以下部分.这是路由嵌套文件夹结构的具体示例.

index.js
/api
  index.js
  /admin
    index.js
    /users
      index.js
      list.js
    /permissions
      index.js
      list.js
Run Code Online (Sandbox Code Playgroud)

这是节点如何工作的一般示例.如果在文件夹中使用"index.js"类似于"index.html"在网页中如何在目录默认情况下工作,则可以很容易地根据递归扩展您的组织,而无需将入口点更改为代码."index.js"是在目录中使用require时访问的默认文档.

index.js的内容

const express = require('express');
const router = express.Router();
router.use('/api', require('./api'));
module.exports = router;
Run Code Online (Sandbox Code Playgroud)

/api/index.js的内容

const express = require('express');
const router = express.Router();
router.use('/admin', require('./admin'));
module.exports = router;
Run Code Online (Sandbox Code Playgroud)

/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;
Run Code Online (Sandbox Code Playgroud)

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

const express = require('express');
const router = express.Router();
router.get('/', require('./list'));
module.exports = router;
Run Code Online (Sandbox Code Playgroud)

这里可能存在一些DRY问题,但它确实可以很好地解决问题.

仅供参考,最近我进入了actionhero并发现它是全功能的w/socket和任务,更像是真正的框架一体化翻转REST范例.你可能应该通过赤身裸体的快递来检查它.

  • 我看到这是如何拆分路线的,但是它如何解决嵌套? (11认同)
  • 5年过去了,看起来仍然很不错,谢谢! (2认同)

Sso*_*esS 8

本着 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;
Run Code Online (Sandbox Code Playgroud)

物品路由器

// 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;
Run Code Online (Sandbox Code Playgroud)

来源


Jor*_*ias 7

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);
Run Code Online (Sandbox Code Playgroud)

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

var itemRouter = require('express').Router({ mergeParams: true }); 
Run Code Online (Sandbox Code Playgroud)

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

{"user_id":"jordan","item_id":"cat"}
Run Code Online (Sandbox Code Playgroud)


Pie*_*R-A 7

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

服务器.ts

import Routes from './api/routes';
app.use('/api/', Routes);
Run Code Online (Sandbox Code Playgroud)

/api/routes/index.ts

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

const router = Router();

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

export default router;
Run Code Online (Sandbox Code Playgroud)

/api/routes/home.ts

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

const router = Router();

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

export default router;
Run Code Online (Sandbox Code Playgroud)