簡體   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