Доступ к промежуточному программному обеспечению для req.params

Я хотел бы выделить фрагмент кода, который будет проверять либо req.params, либо req.body для значения, которое требуется для каждого запроса. Я нахожу, что если я попытаюсь получить доступ к этим значениям до app.use(app.router), тогда запрос не будет проанализирован для включения этих объектов. Если я попытаюсь вставить промежуточное ПО после app.use(app.router), тогда он будет пропущен вместе.

Что я могу сделать, чтобы работать с этими значениями в одном месте, чтобы работа была готова к использованию маршрутами и моделями, расположенными ниже по течению?

Ответ 1

Вы не можете делать то, что вы пытаетесь сделать. https://github.com/strongloop/express/issues/2088 объясняет это очень четко.

Я пытаюсь сделать то, что вы пытаетесь сделать в течение некоторого времени, без успеха. Я, наконец, проследил эту проблему в github.

Ответ 2

Просто запустите промежуточное программное обеспечение с каждым маршрутом,

const middleware = (req, res, next) => {
    console.log(req.params.id);
    next();
};

app.get('/test/:id', middleware, (req, res) => {
    res.send('hi');
});

Ответ 3

Поскольку мой первоначальный ответ не будет получать параметры маршрута из URL-адреса, например. /things/:foo (хотя он получит параметры querystring и req.body), он не будет работать так, как мы хотим. Но другой вариант - написать функцию-оболочку, которая сделает все, что вам нужно, и применить ее к промежуточному программному обеспечению маршрута:

function checkForParam (fn) {

    return function(req, res, next) {

       if (req.param('foo') != 'bar') {
          return res.send(403, 'No way Jose!');
       }

       fn (req, res, next);

    };

}

Затем добавьте маршруты с помощью:

app.get('/things/:foo', checkForParam(function(req, res, next) {
  // your middleware code here
});

Это запустит проверку и перейдет к вашему настраиваемому промежуточному программному обеспечению маршрута только в том случае, если оно пройдет.

Ответ 4

Мне нравится этот способ:

const controller = function (name, method) {
  return function (req, res) {
    // COERCE ID
    if (req.method === 'GET' || req.method === 'DELETE') {
      var _id = req.params && req.params._id || false
      if (/^[0-9a-f]{24}$/.test(_id)) {
        req.params._id = new ObjectID(_id)
      }
      else if (_id) {
        return res.status(404).send('Page not found.')
      }
    }
    require('./api/' + name + '.js')[method](req, res)
  }
}

Затем:

app.get('/api/post/:_id', controller('posts', 'get'))

Ответ 5

Остается один вопрос: используете Express v. 3 или 4

Это очень важно здесь, потому что понятие в версии 4 отличается (также лучше).

например. https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x

app.use(app.router);//< --- эта строка будет удалена

Ответ 6

Вместо того, чтобы пытаться сделать это с помощью специального промежуточного программного обеспечения, вы можете просто добавить шаблон подстановки, который всегда будет выполняться перед вашими другими маршрутами, и проверить там параметр:

app.get('/*', function(req, res, next) {

   if (req.param('foo')) {
      // Do something
      return next(); // or return res.send(403, 'no way!'), or whatever.
   } 

   return next();

});