【问题标题】:Use specific middleware in Express for all paths except a specific one对除特定路径之外的所有路径使用 Express 中的特定中间件
【发布时间】:2012-10-06 23:07:44
【问题描述】:

我在 node.js 中使用 Express 框架和一些中间件功能:

var app = express.createServer(options);
app.use(User.checkUser);

我可以使用带有附加参数的.use 函数来仅在特定路径上使用此中间件:

app.use('/userdata', User.checkUser);

是否可以使用路径变量,以便将中间件用于除特定路径(即根路径)之外的所有路径?

我正在考虑这样的事情:

app.use('!/', User.checkUser);

所以User.checkUser 总是被调用,除了根路径。

【问题讨论】:

    标签: node.js routes express middleware


    【解决方案1】:

    不是直接将User.checkUser 注册为中间件,而是注册一个新的帮助函数,比如checkUserFilter,它会在每个 URL 上调用,但仅在给定的 URL 上将执行传递给 userFiled`。示例:

    var checkUserFilter = function(req, res, next) {
        if(req._parsedUrl.pathname === '/') {
            next();
        } else {
            User.checkUser(req, res, next);
        }
    }
    
    app.use(checkUserFilter);
    

    理论上,您可以提供到app.use 的正则表达式路径。例如:

    app.use(/^\/.+$/, checkUser);
    

    在 express 3.0.0rc5 上试过了,还是不行。

    也许我们可以open a new ticket 并建议将此作为一项功能?

    【讨论】:

    • 我认为这仅从 v4 开始支持。
    【解决方案2】:

    我会将 checkUser 中间件添加到我的所有路径中,主页除外。

    app.get('/', routes.index);
    app.get('/account', checkUser, routes.account);
    

    app.all('*', checkUser);
        
    function checkUser(req, res, next) {
      if ( req.path == '/') return next();
    
      //authenticate user
      next();
    }
    

    您可以扩展它以在未经过身份验证的路径数组中搜索 req.path:

    function checkUser(req, res, next) {
      const nonSecurePaths = ['/', '/about', '/contact'];
      if (nonSecurePaths.includes(req.path)) return next();
    
      //authenticate user
      next();
    }
    

    【讨论】:

    • 是否可以允许所有请求到特定路径,但不允许子路径? (即“/”、“/style.css”、“/background.jpg”,但不是“/lists/”或“/titles”)
    • 您的静态资产应从静态目录中提供。
    【解决方案3】:

    使用

    app.use(/^(\/.+|(?!\/).*)$/, function(req, resp, next){...
    

    这会传递除 / 之外的任何 url。除非,它对我有用。

    一般

    /^(\/path.+|(?!\/path).*)$/
    

    (见How to negate specific word in regex?

    希望对你有帮助

    【讨论】:

      【解决方案4】:

      您也可以在每个路由上设置中间件。

      // create application/x-www-form-urlencoded parser
      var urlencodedParser = bodyParser.urlencoded({ extended: false })
      
      // POST /login gets urlencoded bodies
      app.post('/login', urlencodedParser, function (req, res) {
        if (!req.body) return res.sendStatus(400)
        res.send('welcome, ' + req.body.username)
      })
      

      【讨论】:

        【解决方案5】:

        使用这个名为express-unless的库

        要求对每个请求进行身份验证,除非路径是 index.html。

        app.use(requiresAuth.unless({
          path: [
            '/index.html',
            { url: '/', methods: ['GET', 'PUT']  }
          ]
        }))
        

        Path 它可以是字符串、正则表达式或任何这些的数组。它也可以是一个对象数组,它是 URL 和方法键对。如果请求路径或路径与方法匹配,则中间件不会运行。

        这个库一定会对你有所帮助。

        【讨论】:

          【解决方案6】:

          @chovy 的解决方案是最好的。

          另一种解决方案是:

          我遇到了类似的问题。所以我所做的就是将“路​​由”文件中的函数拆分成不同的文件,分别导出。同样,我将它们分别导入“服务器”文件中,并为各自的路由调用中间件。但我不会大规模推荐这个,我有一个不到 10 条路线的小项目,所以我不介意这样做。对于缩放,我会选择 chovy 的方法。

          【讨论】:

            【解决方案7】:

            解决方法是使用设置api和中间件的顺序。在你的情况下,它必须是这样的。

             var app = express.createServer(options);
                
                // put every api that you want to not use checkUser here and before setting User.checkUser
                app.use("/", (req, res) => res.send("checkUser middleware is not called"));
                
                
                app.use(User.checkUser);
                
                // put every api that you want use checkUser
                app.use("/userdata", User.checkUser, (req, res) =>
                  res.send("checkUser called!")
                );
            

            这是一个完整的例子。

            const express = require("express");
            const app = express();
            const port = 3002;
            
            app.get("/", (req, res) => res.send("hi"));
            
            app.use((req, res, next) => {
              console.log("check user");
              next();
            });
            
            app.get("/checkedAPI", (req, res) => res.send("checkUser called"));
            
            app.listen(port, () => {
              console.log(`Server started at port ${port}`);
            });
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-10-28
              • 1970-01-01
              • 2010-09-06
              • 2011-09-23
              • 2021-03-26
              • 1970-01-01
              相关资源
              最近更新 更多