Промежуточное программное обеспечение Express Router вызывается несколько раз - PullRequest
0 голосов
/ 25 января 2019

Использование Express и Express Router. У меня есть несколько файлов в одном каталоге, которые все реализуют Express.Router. Я динамически требую их, добавив некоторое промежуточное программное обеспечение и затем подключив их к «мета» маршрутизатору и, наконец, позвонив app.use("/",MetaRouter).

Моя проблема в том, что промежуточное ПО вызывается несколько раз для каждого маршрута.

Вот /index.js:

const express = require('express')
const bodyParser = require('body-parser');
const app = express();
const port = 4000;
var cors = require('cors')
var routes = require('./routes');

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use(routes);

app.listen(port, '0.0.0.0', () => console.log(`Example app listening on port ${port}!`))

Что требует /routes/index.js:

const fs = require('fs');
const path = require('path');
var express = require('express');
var MetaRouter = express.Router();
var passport = require('passport');

const files = fs.readdirSync(__dirname).filter(file => file !== 'index.js');      

const fileModules = {};

var middleware = function(req, res, next) {
    console.log('In The Middleware');
    next();
  }


files.forEach(file => {
    const { name } = path.parse(file); 
    fileModules[name] = require(`./${name}`);
});

Object.entries(fileModules).forEach(([key, _router]) => {
    _router.use(middleware);
    MetaRouter.use(_router);

});

module.exports = MetaRouter;

А вот пример одного из файлов маршрутизатора в каталоге:

const BoxRequestService = require("../services/request/box_request_service.js");
var express = require('express');
var router = express.Router();

router.get('/box',
  async function (req, res) {
      res.json(await BoxRequestService.getAll(req, res));
  });

router.get('/box/:id',
  async function (req, res) {
    res.json(await BoxRequestService.findById(req, res));
  }
);

router.put('/box/:id',
  async function (req, res) {
    res.json(await BoxRequestService.update(req, res));
  });

router.post('/box', async function (req, res) {
  res.json(await BoxRequestService.create(req, res));
});

module.exports = router;

Ожидаемые результаты

Так что при запросе http://localhost/box, я ожидаю увидеть «In the Middleware» в консоли ровно один раз.

Фактические результаты

Вместо этого я вижу, что "В промежуточном программном обеспечении" зарегистрировано несколько раз. Это также зависит от порядка, в котором файлы требуются. Итак, учитывая этот список файлов (требуется в этом порядке):

  • / маршруты / B.js
  • / маршруты / C.js * * тысячу тридцать-три
  • / маршруты / D.js * +1035 *

Если запрашивается маршрут в A.js, промежуточное ПО вызывается один раз. Если запрашивается маршрут в B.js, промежуточное программное обеспечение вызывается дважды. Если запрашивается маршрут в C.js, промежуточное программное обеспечение вызывается три раза. и т.п. и т.д.

1 Ответ

0 голосов
/ 25 января 2019

Express промежуточное программное обеспечение подключено не для каждого экземпляра маршрутизатора, а для каждого пути. Поскольку я не указывал путь, мой вызов _router.use(middleware); был привязан к промежуточному программному обеспечению ко всем путям. И поскольку я вызывал это в цикле, я просто добавлял одно и то же промежуточное ПО несколько раз ко всем путям.

Чтобы исправить это и получить преимущества динамического запроса отдельных файлов маршрутизатора, я внес некоторые изменения в свой код.

Прежде всего, я добавил небольшой объект «метаданных» в каждый из файлов роутера. У него есть два поля. Один содержит «префикс маршрута» (путь, с которого начинается каждый из маршрутов в файле) и что-то, что говорит о необходимости авторизации маршрутов в этом файле (мое промежуточное ПО выполняет авторизацию).

Затем я экспортирую и маршрутизатор, и метаданные из этого файла маршрутизатора.

Теперь вернемся к моему файлу `/routes/index.js '...

Там я все еще динамически запрашиваю все индивидуальные маршруты и прикрепляю промежуточное программное обеспечение. Однако я использую метаданные маршрутизатора для подключения маршрутизатора с использованием его префикса, поэтому я не применяю промежуточное ПО к одним и тем же путям маршрутов снова и снова.

/routes/index.js

const fs = require('fs');
const path = require('path');
const auth_service = require('./../utils/auth_service');
var express = require('express');
var MetaRouter = express.Router();

// collect all of the legitimate router files
const files = fs.readdirSync(__dirname).filter(file => file !== 'index.js');

// pull in each "child" router, attach it to the "meta router" and apply middleware
files.forEach(file => {
    const { name } = path.parse(file);
    _router = require(`./${name}`);
    MetaRouter.use(_router.router_metadata.endpoint_prefix, auth_service.auth_middleware(_router.router_metadata), _router.router);
});

module.exports = MetaRouter;

один из моих файлов роутера

const BoxRequestService = require("../services/request/box_request_service.js");
var express = require('express');
var router = express.Router();

const router_metadata = {
  endpoint_prefix: '/box',
  requires_auth: true
}

router.get('/:id',
  async function (req, res) {
    res.json(await BoxRequestService.findById(req, res));
  }
);

router.put('/:id',
  async function (req, res) {
    res.json(await BoxRequestService.update(req, res));
  });

router.post('/', async function (req, res) {
  res.json(await BoxRequestService.create(req, res));
});

router.get('/',
  async function (req, res) {
    res.json(await BoxRequestService.getAll(req, res));
  });

module.exports = { router, router_metadata }; 

И вот где я определяю промежуточное ПО

Здесь я использую метаданные маршрутизатора, чтобы определить, должно ли промежуточное ПО применяться к его путям.

var passport = require('passport');
require('../config/passport')(passport);

let self = module.exports = {

    auth_middleware: function(router_metadata){
        return function (req, res, next) {
            if (router_metadata.requires_auth) {
                passport.authenticate('jwt', { session: false }, function (err, user, info) {
                    if (err) { return next(err); }
                    if (!user) {
                        res.status("401");
                        return res.send("Unauthorized").end();
                    }
                    req.user = user;
                    next();
                })(req, res, next);
            } else {
                next();
            }
        }
    }

}
...