简体   繁体   English

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

[英]Assigning middlewares to specific actions in ActionHero

Is the anyway to add some middleware to specific actions? 无论如何,是否要在特定操作中添加一些中间件? because as far as I know addPreProcessor adds the middleware to all the actions? 因为据我所知,addPreProcessor将中间件添加到所有操作中? lets say you don't want to have authentication or some other checks on some actions, is there any solution? 假设您不想对某些操作进行身份验证或其他检查,是否有解决方案?

I have a short term solution but it would be nice if you could assign your specific middlewares when you're defining your action(like giving an array of middleware names that need to be run, in order) 我有一个短期解决方案,但是如果您在定义操作时可以分配特定的中间件(例如,按顺序给出需要运行的一系列中间件名称),那就太好了。

My current solution is keeping an array of all the actions that I need to apply the middleware to them and then check it against the connection.aciton, but then still every single request goes through all the middlewares and then it gets passed around which it doesn't sound efficient to me! 我当前的解决方案是保留将中间件应用于它们的所有操作的数组,然后根据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();
}

Thanks in advance ! 提前致谢 !

No need to do all that! 不需要做所有的事情! Check out this example from the docs: https://github.com/evantahler/actionhero-tutorial/blob/master/initializers/middleware.js 从文档中查看以下示例: 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();
}

Yes, all middlewares fire for all actions, but you can tell the middleware to inspect the action's definition, and look for a specific property. 是的,所有中间件都会触发所有动作,但是您可以告诉中间件检查动作的定义,并查找特定的属性。 In this case, we only care if the action looks like this: 在这种情况下,我们只关心动作是否如下所示:

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);
  }

};

Ok I think I found a better solution and I would like to know your opinion. 好的,我想我找到了一个更好的解决方案,我想知道您的意见。

So I just added middlewares : ['middlewareOne', 'middlewareTwo'] to my actions, which the order of execution is equal to order of middleware names in the array and then my middlewares initialiser is like this 所以我只是在操作中添加了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();
} 

Any thoughts? 有什么想法吗?

EDIT1: next(connection, false); EDIT1: next(connection, false); don't send anything to user, I guess you always want to send an error response or something to the user even if the execution middlewares stop after one of them wasn't successful and returned a next(connection, false) . 不要将任何内容发送给用户,我猜您始终希望向用户发送错误响应或某些内容,即使执行中间件在其中一个失败之后停止并返回了next(connection, false) In this case in the eachSeries final callback function I guess we always have to use next(connection, true); 在这种情况下,在eachSeries最终回调函数中,我想我们总是必须使用next(connection, true); ;。 !!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM