有条件地使用中间件取决于请求参数表达

时间:2014-01-21 23:51:43

标签: node.js express

我正在尝试根据请求查询参数决定使用中间件。

在主模块中我有这样的东西:

app.use(function(req, res){
  if (req.query.something) {
    // pass req, res to middleware_a
  } else {
    // pass req, res to middleware_b
  }
});

middleware_amiddleware_b 两个表达应用本身由express()函数创建,而不是常规中间件函数(function(req, res, next)

无法找到办法

8 个答案:

答案 0 :(得分:24)

连接/表达'中间件'并不神奇:它们只是功能 - 您可以像调用任何其他功能一样调用它们。

所以在你的例子中:

app.use(function(req, res, next){
  if (req.query.something) {
    middlewareA(req, res, next);
  } else {
    middlewareB(req, res, next);
  }
});

也就是说,可能有更优雅的方式来构建分层表达应用程序。查看TJ's video

答案 1 :(得分:8)

我知道这个问题已经过时了,但我想分享一下我的解决方案。我通过创建一个返回带有回调的中间件的函数来解决这个问题。

示例中间件:

function isAdminUser(callback){
    return function(req, res, next){
        var userId = callback(req);
        // do something with the userID
        next();
    }
}

然后,您可以在快速路由器对象

中执行以下操作
app.use(isAdminUser(function(res){
    return res.body.userId
    });

答案 2 :(得分:6)

我不会使用该中间件 - 而是在中间件A和B中检查以下内容:

//Middleware A
app.use(function(req, res){

  // If it doesn't match our condition then send to next middleware
  if (!req.query.something) {
    next();
  } else {
    // We're good - let this middleware do it's thing
    ...
    next();
   }
});

与中间件B相同

//Middleware B
app.use(function(req, res){

  if (req.query.something) {
    ...
});

答案 3 :(得分:1)

看起来你可能错过了这个伎俩。 每个中间件都是请求处理程序。首先查看第一个请求处理程序,然后查看下一个请求处理程序,然后查看下一个,依此类推。

以下是中间件的基本外观:

function myFunMiddleware(request, response, next) {
// Do stuff with the request and response.
// When we're all done, call next() to defer to the next middleware.
next();
}

我建议你修改你的代码。

app.use(function(request, response, next) {
  if (request.url == "/") {
  response.writeHead(200, { "Content-Type": "text/plain" });
  response.end(".. Any custom msg..\n");
 // The middleware stops here.
  } 
  else {
  next();
}});

请通过此tutorial,我相信您将对使用中间件有一个很好的概述。有一个快乐的编码。

答案 4 :(得分:1)

我知道我对这个帖子有点迟,但你可以使用这个插件 Express Conditional Tree Middleware

它允许您组合多个和异步中间件。 具体来说,您可以创建两个代表中间件的类(middleware_a,middleware_b),并且驻留在这些类中的applyMiddleware方法内部将返回由中间件函数创建的承诺或自定义解析的承诺。你的中间件功能了。

然后在你的主js文件中,你可以创建一个chainer,根据你的需要有条件地组合这些中间件!查看文档以获取更多信息,检查代码后会更清楚。

答案 5 :(得分:0)

如果您像我一样在这里着陆,希望在有条件的中间件(例如护照或会议)下使用第三方中间件,这是您的操作方式:

app.use((req, res, next) => {
    // your condition
    if (req.url !== 'no-session') {
      // Your middleware
      session()(req, res, next);
    } else {
      next();
    }
  })

这仅在满足条件时触发会话。您必须将(req,res,next)作为第二个函数的参数发送给第二个函数,始终将其返回以连接中间件。对于任何中间件,无论是您自己的还是第三方的,它都适用。

答案 6 :(得分:0)

我也有同样的需求,所以我创建了一个包装程序来创建条件中间件。

const conditionalMiddleWare = function(condition) {
  return function(middleware) {
    return function(req, res, next) => {
      if (
        (typeof condition == 'boolean' && condition) ||
        (typeof condition == 'function' && condition(req, res, next))
      ) {
        return middleware(req, res, next);
      }
      next();
    };
  }
}

您可以将其与布尔值一起使用

// Only use this middleware on production environment
forProduction = conditionalMiddleWare(server.settings.env === 'production');
server.use(forProduction(auth.connect()));

您可以根据要求使用功能即时决定

// Only use this middleware when it's not the `/api/` folder that is requested
const forNotApi = conditionalMiddleWare(function(req) {
 return !req.path.startsWith('/api/');
});
server.use(forNotApi(express.static(rootDir)));

我希望它能有所帮助!

答案 7 :(得分:0)

对于异步函数,你可以这样做:


// Generic middleware style function.
const processData = async(data) => {
  // Do some processing.
  const processedData = await something(data);
  if (response.error) {
    return [{message: "There was an error"}];
  }
  return [ false, processedData ]
}


const routeMiddleware = async(req, res, next) => {
  if (req.body.data.property === 'a') {
    const [ err, processedData] = await processData(req.body.data);
    if (err) next(err);
    return res.json({ message: 'Successfully processed', processedData});
  } else {
    return res.json({ message: 'Not processed'});
  }
}

这种模式的优点:

  • processData() 函数可以在应用程序的其他地方重用
  • 易于阅读
  • 使用异步/等待

在异步函数调用周围包裹一个 try/catch 块也可能是一个好主意,或者使用 @awaitjs/express。