javascript - How to make dynamic chain of middleware in express.js -


i working on project develop api manager control existing api.

it contains list of "before" , "after" middlewares, used things security checking , logging. , "service" middleware http request existing api. problem want make order middleware being executed dynamic, meaning load configuration file change order middleaware executed every time request comes in.

here previous code:

'use strict'; // loading express library var express = require('express'); var app = express();  var service = require('./routes/index');   // testing configurable middleware var confirguration = {     before1: {         priority: 100,         enable: true     },     before2: {         priority: 80,         enable: true     },     service: {         priority: 50,         enable: true     },     after1: {         priority: 30,         enable: true     },     after2: {         priority: 10,         enable: true     } }  var before1 = require('./example_middleware/before1'); var before2 = require('./example_middleware/before2'); var after1 = require('./example_middleware/after1'); var after2 = require('./example_middleware/after2'); // fake request simulate /service var fakerequest = require('./example_middleware/fake_request');  // function sort order of middleware executed var sortconfig = function(confirguration){     var sortable = [];     (var middleware in confirguration)         // make middlewares configurable         if (confirguration[middleware]['enable'] == true){             sortable.push([middleware, confirguration[middleware]['priority']]);         }      sortable.sort(function(a, b) {return b[1] - a[1]});     return sortable; }  // var sortedconfig = []; var middlewareset = new array(); app.use('/test', function(request, response, next){     var middleware;     var sortedconfig = sortconfig(confirguration);      (var in sortedconfig){         switch(sortedconfig[i][0]){             case 'before1':                 middleware = before1;                 break;             case 'before2':                 middleware = before2;                 break;             case 'service':                 middleware = fakerequest;                 break;             case 'after1':                 middleware = after1;                 break;             case 'after2':                 middleware = after2;                 break;         }           // console.log(sortedconfig[i][0]);         // execute middleware in expected order         middlewareset.push(middleware);     }     // request.sortedconfig = sortedconfig;     console.log(middlewareset);     console.log('middleware list sorted');     next(); });  app.use('/test', middlewareset); 

but keep getting same error message coming app.use() @ last line:

app.use() requires middleware functions

it works if use:

app.use('/test', [before1, before2, fakerequest, after1, after2]); 

but it's not dynamic though, did misunderstand? there must way in express.js.

thanks in advance.

edit: modified code according ryan's answer, here code:

var async = require('async'); app.use('/test', configurablemiddleware);  function configurablemiddleware(req, res, next) {      var operations = [];      var middleware;      var sortedconfig = sortconfig(confirguration);     // push each middleware want run     sortedconfig.foreach(function(fn) {          switch(fn[0]){             case 'before1':                 middleware = before1;                 break;             case 'before2':                 middleware = before2;                 break;             case 'service':                 middleware = fakerequest;                 break;             case 'after1':                 middleware = after1;                 break;             case 'after2':                 middleware = after2;                 break;         }          operations.push(middleware); // use fn.bind(null, req, res) pass in vars       });      console.log('middleware list sorted');    // invoke middleware in series     async.series(operations, function(err) {         if(err) {         // 1 of functions passed error handle here             return next(err);         }       // no errors pass control express         next();     });  } 

just make sure haven't made mistakes in test middleware, here example of 1 of them:

'use strict';  var express = require('express'); var router = express.router();  router.route('/')     .all(function(request, response, next){         console.log('this middleware before1');         next();     });   module.exports = router; 

now, when run application, got following error npm:

typeerror: cannot call method 'indexof' of undefined

at function.proto.handle (/users/jialunliu/documents/soa_project/fat-lady/node_modules/express/lib/router/index.js:130:28) @ router (/users/jialunliu/documents/soa_project/fat-lady/node_modules/express/lib/router/index.js:35:12) @ /users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:610:21 @ /users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:249:17 @ iterate (/users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:149:13) @ async.eachseries (/users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:165:9) @ _asyncmap (/users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:248:13) @ object.mapseries (/users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:231:23) @ object.async.series (/users/jialunliu/documents/soa_project/fat-lady/node_modules/async/lib/async.js:608:19) @ configurablemiddleware (/users/jialunliu/documents/soa_project/fat-lady/app.js:135:11)

which coming line async.series(operations, function(err){})

i keep getting kind of error message, saying function not read array of functions "operations"....

i think on right track, need tweak few things. register 1 top level function app.use() , of dynamic stuff within function. updating answer working example. sure install async first npm install --save async

// define middleware functions var middleware = {     mw1: function(req, res, next) {         console.log('mw 1');         next();     },     mw2: function(req, res, next) {         console.log('mw 2');         next();     },     mw3: function(req, res, next) {         console.log('mw 3');         next();     },     mw4: function(req, res, next) {         console.log('mw 4');         next();     }  };  // register our "top level function" app.use(configurablemiddleware); var requestcount = 1; // working example  function configurablemiddleware(req, res, next) {     var isevenrequest = requestcount++ % 2 === 0; // simple logic alternate "configurable" middleware use      var operations; // in real world build array dynamically, hardcode 2 scenarios example      // each request http://localhost:3000 alternate middleware used, see different log each time     if(isevenrequest) {         console.log('even request should log mw2 , mw4');         // .bind(null, req, res) makes sure middleware gets request , response objects when invoked,          // of point still haven't been invoked...         operations = [middleware.mw2.bind(null, req, res), middleware.mw4.bind(null, req, res)];     }     else {         console.log('odd request should log mw1 , mw3');         operations = [middleware.mw1.bind(null, req, res), middleware.mw3.bind(null, req, res)];     }      // invoke each middleware in series - async.parallel if order of middleware doesn't matter     // using async module: https://github.com/caolan/async     async.series(operations, function(err) {         if(err) {             console.log('there problem running middleware!');             return next(err);         }         // middleware has been run         next();     }); } 

for more info on .bind() see https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/function/bind


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -