我希望能够在运行时添加新路由,而无需使用 NodeJS 和 ExpressJS 重新启动服务器。我在这篇文章中做了一个类似的方法:https
://alexanderzeitler.com/articles/expressjs-dynamic-runtime-routing/从技术上讲,我同样可以在文章中在运行时添加新文件和逻辑,但问题是当没有匹配 api 路由时,我将发送一个 404 JSON 响应(因为它应该是)。
我认为我遇到的问题是我的动态创建的路由永远不会到达,因为静态路由优先于动态创建的路由。这意味着创建的路由将在错误处理后挂载,因此永远不会到达。我在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;
当我注释掉错误处理时,我能够访问我在运行时创建的路由,而通过错误处理,我只能在服务器重启后访问我想要避免的动态创建的路由。
查询参数无法解决问题,因为动态添加的路由在逻辑、模型属性、http 方法/动词和 API 端点上有所不同。例如
GET/POST /api/{endpoint}
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'});
}
}
...
片段中的控制器只是一个模块化控制器文件,它处理我对不同模型的所有端点的所有 CRUD 操作。每条路由都分为模型、控制器和路由,以分离和更好地维护它们的逻辑。
在 POST 方法中,我首先检查要创建的端点是否已经存在。如果是这样,我会以 422 响应,表明端点已经存在。如果它不存在,我会在数据库端点中创建一个带有模块化控制器的条目,并为应该创建的端点创建一个模型、控制器和路由。
创建逻辑如下:
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 方法传递到异步创建的模型、控制器和路由文件。创建所有文件后,我将端点路由安装到应用程序。挂载路由的逻辑是:
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 包括一些用于授权/身份验证的逻辑。
该代码几乎完成了我想要它做的事情,只是我不知道如何在错误处理之前处理路线的定位。