使用 Express.js 嵌套路由器进行休息可管理的嵌套路由...

2022-08-30 01:50:46

假设我想要有 REST 端点,它看起来大致如下:

/user/
/user/user_id 

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

每个 IF 上的 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);

URL to 是 的 URL 层次结构的后代。现在,我如何获取URL,其中包含任何指向用户路由的内容,但更具体的路由到项目路由?而且,如果可能的话,我希望user_id也可以访问itemRouter。itemuser/users/user/*user_id*/items/


答案 1

您可以通过将路由器作为中间件附加到其他路由器上(无论是否使用 ) 来嵌套路由器。params

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

mergeParamsExpress 4.5.0 中引入 (2014 年 7 月 5 日)

在此示例中,获取附加到路线上的itemRouteruserRouter/: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);

答案 2

可管理的嵌套路由...

我想要一个在express 4中以非常易于管理的方式执行嵌套路由的特定示例,这是“Express中的嵌套路由”的顶级搜索结果。例如,这是一个API,它将具有许多需要拆分的路由。

./索引.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”在目录默认值的网页中的工作方式,这将很容易根据递归扩展您的组织,而无需将入口点更改为代码。“index.js”是在目录中使用 require 时访问的默认文档。

索引内容.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问题,但它确实非常适合封装关注点。

仅供参考,最近我进入了actionhero,并发现它是功能齐全的w / sockets和任务,更像是一个真正的框架,一体化翻转了REST范式。你应该检查一下,而不是裸体w/快递。