javascript - 在 NodeJs 中间件中使用异步函数的问题
问题描述
当我尝试从中间件代码中的 Redis DB 加载黑名单的初始数据时遇到问题。由于数据库请求需要一些时间,它开始失败。
下面是我的代码,当应用程序通过app.use(blacklist.blockRequests());
.
当我尝试使函数异步时,我收到错误消息new TypeError('app.use() requires a middleware function')
。
副作用之一是我的数组在再次调用时为空。
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;
},
这是我的read()
功能代码:
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 = [];
}
}
}
解决方案
如果您尝试进行blockRequests()
异步,那么它将开始返回一个承诺,并且您不能直接在app.use()
. 因为那样你会这样做app.use(somePromise)
,而 Express 会犹豫,因为你必须向它传递一个函数引用,而不是一个承诺。
相反,您将不得不使用.then()
orawait
获取返回值,这是您可以使用的函数app.use()
。
如果您在此处显示更大的调用上下文(例如您从哪里调用blockRequests()
),那么我们可以提供更多关于更完整解决方案的想法。
这是一个关于如何做到这一点的概念性想法:
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);
});
推荐阅读
- vb.net - 带有标题面板(标题)和面板下方菜单的 Devexpress 表单
- internet-explorer-11 - 使用 Internet Explorer 在 App-V 序列中打开本地 HTM 文件
- excel - 如何引用 Excel 表格中的单元格
- css - 带有 Bootstrap 的 React 组件的页面布局 - 页脚未保留在原位
- bash - 用于拆分第 n 个字段文本并作为新行插入的 awk 命令
- android - 是否可以动态更改 Android EditText 上的自动填充提示
- javascript - 在 javascript 中应用 Object.entries 后扩展数组
- typescript - AWS CDK Typescript 问题:预期的类型来自属性“securityGroups”,该属性在“InstanceProps”类型上声明
- javascript - 正则表达式字符恰好出现两次
- r - 如何从数据框中排除与另一个数据框同一列中的行匹配的行?