2

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

基本的に次のいずれかが必要だと思い
ます。エラー処理の前に動的に作成されたルートをマウントする方法-現在行き詰まっているか、または
2)ルートスタックを変更します-私が読んだことは非現実的で、遅く、悪い習慣であり、エラーが発生しやすいです
3)代替ソリューションを見つけます

誰かが私を助けてくれることを願っています。
よろしくお願いします

EDIT
新しいルートを作成するためのコードは次のとおりです。関連するエンドポイントは、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 には、承認/認証のためのいくつかのロジックが含まれています。

コードは、エラー処理の前にルートの配置を処理する方法がわからないことを除いて、私がやりたいことのほとんどを行います。

4

1 に答える 1

4

特急ルートは作成順での取り扱いとなります。

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);
}
于 2020-08-01T03:38:40.593 に答える