将中间件分配给ActionHero中的特定操作

时间:2015-01-11 02:16:11

标签: javascript node.js middleware actionhero

无论如何要为特定操作添加一些中间件吗? 因为据我所知addPreProcessor将中间件添加到所有操作中?假设您不想对某些操作进行身份验证或其他检查,是否有任何解决方案?

我有一个短期解决方案,但如果您可以在定义操作时分配特定的中间件(比如提供一系列需要按顺序运行的中间件名称),那就太好了。

我当前的解决方案是保留一系列我需要将中间件应用于他们的所有操作,然后针对connection.aciton检查它,但是然后仍然每个请求都通过所有中间件然后它传递它对我来说听起来不高效!

exports.middlewares = function(api, next){

    var myImportantMiddleware = function(connection, actionTemplate, next) {

        var actionsToBeChecked = ['deposit'];
        var action = connection.action;

        if(actionsToBeChecked.indexOf(action) > -1) {
                /*  middleware logic 
                next(connection, true); */
        } else {
            next(connection, true);
        }
    }

    api.actions.addPreProcessor(myImportantMiddleware);

    next();
}

提前致谢!

2 个答案:

答案 0 :(得分:1)

无需做所有这些!请查看文档中的此示例:https://github.com/evantahler/actionhero-tutorial/blob/master/initializers/middleware.js

exports.middleware = function(api, next){

  var authenticationMiddleware = function(connection, actionTemplate, next){
    if(actionTemplate.authenticated === true){ // <-- HERE
      api.users.authenticate(connection.params.userName, connection.params.password, function(error, match){
        if(match === true){
          next(connection, true);
        }else{
          connection.error = "Authentication Failed.  userName and password required";
          next(connection, false);
        }
      });
    }else{
      next(connection, true);
    }
  }

  api.actions.addPreProcessor(authenticationMiddleware);

  next();
}

是的,所有中间件都会触发所有操作,但您可以告诉中间件检查操作的定义,并查找特定属性。在这种情况下,我们只关心动作是否如下所示:

exports.randomNumber = {
  name: 'randomNumber',
  description: 'I am an API method which will generate a random number',
  outputExample: {
    randomNumber: 0.123
  },

  authenticated: true // <<--- HERE

  run: function(api, connection, next){
    connection.response.randomNumber = Math.random();
    next(connection, true);
  }

};

答案 1 :(得分:-1)

好的我觉得我找到了更好的解决方案,我想知道你的意见。

所以我刚刚将middlewares : ['middlewareOne', 'middlewareTwo']添加到我的操作中,执行顺序等于数组中的中间件名称顺序,然后我的中间件初始化程序就像这样

var async = require('async');

exports.middlewares = function(api, next){

    var middlewares = {

        authMiddleware : function(connection, next){
            /* Middleware logic */
        },

        premiumAccessMiddleware : function(connection, next){
            /* Middleware logic */
        },

        adminAccessMiddleware : function(connection, next){
            /* Middleware logic */
        }

    };


    var middlewareProcessor = function(connection, actionTemplate, next){

        var actionMiddlewares = actionTemplate.middlewares;

        async.eachSeries(actionMiddlewares, function(middlewareName, callback){

            var middleware = api.middlewares[middlewareName];

            if(!middleware) throw (new Error("Middleware '"+ middlewareName +"'doesn't exist"));  /* In case I had a typo */

            middleware(connection, function(new_connection, toRender){

                connection = new_connection;

                if(toRender){

                    callback();

                }else{

                    callback('YOU SHALL NOT PASS');
                }

            });

        }, function(err){

            // if(err) return next(connection, false); // see EDIT1

            next(connection, true);

        });

    }

    api.actions.addPreProcessor(middlewareProcessor);

    next();
} 

有什么想法吗?

EDIT1:next(connection, false);不向用户发送任何内容,我猜您总是希望向用户发送错误响应或其他内容,即使执行中间件停止后其中一个不是成功并返回next(connection, false)。在这种情况下,在eachSeries最终回调函数中,我想我们总是必须使用next(connection, true); !!