繁体   English   中英

ExpressJS:在运行时动态添加路由

[英]ExpressJS: Adding routes dynamically at runtime

我希望能够在运行时添加新路由,而无需使用 NodeJS 和 ExpressJS 重新启动服务器。 我在这篇文章中做了一个类似的方法: https://alexanderzeitler.com/articles/expressjs-dynamic-runtime-routing/
从技术上讲,我同样可以在文章中在运行时添加新文件和逻辑,但问题是当没有匹配 api 路由时,我将发送 404 JSON 响应(应该是这样)。

我认为我遇到的问题是我的动态创建的路由永远不会到达,因为 static 路由优先于动态创建的路由。 这意味着创建的路由将在错误处理后挂载,因此永远不会到达。 我在app.js中的代码

 ... // Routes app.use('/api/products', productRoutes); app.use('/api/users', userRoutes); ... /* This is where the dynamically created routes should be mounted */ // Error handling app.use((req, res, next) => { const err = new Error('Not found'); err.status = 404; next(err); }); app.use((err, req, res, next) => { res.status(err.status || 500).json({error: {message: err.message}}); }); /* This is where the dynamic routes are mounted */ module.exports = app;

当我注释掉错误处理时,我能够访问我在运行时创建的路由,而通过错误处理,我只能在服务器重启后访问我想要避免的动态创建的路由。
使用查询参数无法解决问题,因为动态添加的路由在逻辑、model 属性、http 方法/动词和 API 端点方面不同。 例如
GET/POST /api/{端点}
GET/POST /api/foo/{endpoint}
GET/PUT/DELETE /api/foo/bar/{endpoint}/:id

我想我基本上需要:
1)在错误处理之前找到一种方法来安装动态创建的路由 - 我目前被困在或
2)修改路由堆栈——我读过的不切实际、速度慢、做法不好并且容易出错
3) 寻找替代解决方案

我希望有一个人可以帮助我。
提前致谢

编辑
这是创建新路线的代码。 相关端点是 POST 方法中的 /api/databases/

 const Database = require('../models/database'); const controller = require('./template/controller'); const creation = require('../Creation'); ... exports.createOne = (req, res, next) => { if (.creation.findFileInDirectory(`./backend/api/models/${req.body.name.singular}.js`) ||.creation.findFileInDirectory(`./backend/api/controllers/${req.body.name.singular}.js`) ||.creation.findFileInDirectory(`./backend/api/routes/${req.body.name,singular},js`)) { controller,createOne(req, res: next, Database, { modelName. 'database'. }. () => { //creation,createEndpoint(req.body.name, req.body.data; req.body.auth). creation,createEndpoint(req.body,name. req.body; req;body.auth). }): } else { res;status(422).json({message. 'Endpoint exists already'}). } } ...

片段中的 controller 只是一个模块化的 controller 文件,它处理我对不同模型的所有端点的所有 CRUD 操作。 每条路由都分为模型、控制器和路由,以分离和更好地维护它们的逻辑。

在 POST 方法中,我首先检查要创建的端点是否已经存在。 如果是这样,我会以 422 响应,表明端点已经存在。 如果它不存在,我会在数据库端点中创建一个带有模块化 controller 的条目,并为应该创建的端点创建一个 model、controller 和路由。

创建逻辑如下:

 const createEndpoint = (name, data, auth) => { createFile(`./backend/api/models/${name.singular}.js`, model.createModel(capitalize(name.singular), data), () => { createFile(`./backend/api/controllers/${name.singular}.js`, controller.createController({singular: capitalize(name.singular), plural: name.plural}, data.data), () => { createFile(`./backend/api/routes/${name.singular}.js`, route.createRoute({singular: capitalize(name.singular), plural: name.plural}, auth), () => { const app = require('../../app'); mountEndpoints(name.singular, app); }); }); }); };

在这里,我基本上将 POST 方法中的数据传递给异步创建的 model、controller 和路由文件。 创建所有文件后,我将端点路由安装到应用程序。 挂载路由的逻辑是:

 const mountEndpoints = (path, app) => { const module = require(`../routes/${path}`); app.use(`/api/${module.plural? `${module.plural}`: `${path}s`}`, module); }

创建的路由可能如下所示:

 const express = require('express'); const router = express.Router(); const checkAuth = require('../middleware/check-auth'); const ProductController = require('../controllers/product'); router.route('/').get(ProductController.getAll).post(checkAuth, ProductController.createOne); router.route('/:id').get(ProductController.getOne).patch(checkAuth, ProductController.patchOne).delete(checkAuth, ProductController.deleteOne); module.exports = router; module.exports.plural = 'products';

checkAuth 包括一些用于授权/身份验证的逻辑。

该代码几乎完成了我想要它做的事情,只是我不知道如何在错误处理之前处理路线的定位。

快速路线将按创建顺序处理。

要在app定义之后在特定位置添加路由,您可以创建一个占位符路由器并将路由附加到那里而不是app本身。

Express 不支持在定义路由后删除路由,但您可以替换整个路由器

创建一个快速路由器实例(如果需要,甚至是另一个app )来安装动态端点。 每当您想要更改路由时重新定义路由器(除了添加到路由器堆栈的末尾,这是由 express 支持的)。

// Routes
app.use('/api/products', productRoutes);
app.use('/api/users', userRoutes);

let dynamicApiRouter = null

export function setupDynamicRouter(config) {
  dynamicApiRouter = new express.Router()
  // Add routes to dynamicApiRouter from `config`
  dynamicApiRouter[config.method](config.path, config.handler)
}

app.use('/api', (req, res, next) => dynamicApiRouter(req, res, next))

// Error handling
app.use((req, res, next) => {
    const err = new Error('Not found');
    err.status = 404;
    next(err);
});

app.use((err, req, res, next) => {
    res.status(err.status || 500).json({error: {message: err.message}});
});

然后,当您挂载一个新端点时,将路由器传入并删除/api路径前缀,因为它现在在父app的路由器外部处理。

const mountEndpoints = (path, router) => {
  const module = require(`../routes/${path}`);
  router.use(`/${module.plural ? `${module.plural}` : `${path}s`}`, module);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM