Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
79 views
in Technique[技术] by (71.8m points)

javascript - Problem using async functions in NodeJs middleware

I am running into an issue when I try to load the initial data for my blacklist from a Redis DB in my middleware code. Since the DB request takes some time it starts to fail.

Below is my code which gets fired when app starts via app.use(blacklist.blockRequests());.

When I try to make the function async I get the error that new TypeError('app.use() requires a middleware function').

One of the side effects is also that my array is empty when it's called again.

blockRequests: function() {
  this.read();
  this.logEvent('info', 'There are ' + this.blacklist.length + ' address(es) on the blacklist');
  var self = this;

  var interceptor = function(request, response, next) {
    var ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;

    if (self.isInBlacklist(ip)) {
      self.logEvent('warn', 'Rejecting request from ' + ip + ', path and query was ' + request.originalUrl);
      response.status(403).send();
    } else {
      next();
    }
  }

  return interceptor;
},

And here is my read() function code:

read: function() {
  try {
    // get all records with prefix block:: from redis
    redis.redis.keys('block::*', function (err, reply) {
      // reply is null when the key is missing
      if(err){}
      else {
        this.blacklist = []

        for (let i = 0; i < reply.length; i++) {
          let ipInt = reply[i].substring(7)
          let ipStr = ipToInt(ipInt).toIP()
          this.blacklist.push(ipStr)             
        }
      }   
    });
  } catch (error) {
    if (error) {
      this.blacklist = [];
    }
  }
}
question from:https://stackoverflow.com/questions/65909653/problem-using-async-functions-in-nodejs-middleware

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you're trying to make blockRequests() async, then it will start returning a promise and you can't use its return value directly in app.use(). Because then you'd be doing app.use(somePromise) and Express will balk because you have to pass it a function reference, not a promise.

Instead, you will have to use .then() or await to get the return value which is the function which you could then use with app.use().

If you show the larger calling context here (like where you're calling blockRequests() from), then we could offer more ideas on a fuller solution.

Here's a conceptual idea for how you could do this:

blockRequests: function() {
  const self = this;
  const interceptor = function(request, response, next) {
    const ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;

    if (self.isInBlacklist(ip)) {
      self.logEvent('warn', 'Rejecting request from ' + ip + ', path and query was ' + request.originalUrl);
      response.status(403).send();
    } else {
      next();
    }
  }
  return interceptor;
},

read: function() {
    // get all records with prefix block:: from redis
    return new Promise((resolve, reject) => {
        redis.redis.keys('block::*', (err, reply) => {
            if (err) {
                this.blacklist = [];
                reject(err);
            } else {
                this.blacklist = [];
        
                for (let i = 0; i < reply.length; i++) {
                  let ipInt = reply[i].substring(7)
                  let ipStr = ipToInt(ipInt).toIP()
                  this.blacklist.push(ipStr)             
                }
            }
            this.logEvent('info', 'There are ' + this.blacklist.length + ' address(es) on the blacklist');
            resolve();
        });
    });
}


// register middleware for using blacklist
app.use(blacklist.blockRequests());

// now read the blacklist and when that is in place, then start the server
blacklist.read().then(() => {
   // now we know that blacklist.blacklist is up-to-date

   // start your server here

}).catch(err => {
   console.log("Unable to start server - error in reading blacklist");
   process.exit(1);
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...