You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-04 15:02:09 +03:00
Always refresh the server_info after running info; Remove proper auth support for redis < 2.6.11
This commit is contained in:
206
index.js
206
index.js
@@ -97,6 +97,7 @@ function RedisClient (options) {
|
|||||||
this.auth_pass = options.auth_pass;
|
this.auth_pass = options.auth_pass;
|
||||||
this.selected_db = null; // Save the selected db here, used when reconnecting
|
this.selected_db = null; // Save the selected db here, used when reconnecting
|
||||||
this.old_state = null;
|
this.old_state = null;
|
||||||
|
this.send_anyway = false;
|
||||||
this.pipeline = 0;
|
this.pipeline = 0;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
// Init parser
|
// Init parser
|
||||||
@@ -172,6 +173,15 @@ RedisClient.prototype.create_stream = function () {
|
|||||||
this.stream.on('drain', function () {
|
this.stream.on('drain', function () {
|
||||||
self.drain();
|
self.drain();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (this.options.socket_nodelay) {
|
||||||
|
this.stream.setNoDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the command before redis is connected to be sure it's the first fired command
|
||||||
|
if (typeof this.auth_pass === 'string') {
|
||||||
|
this.do_auth();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RedisClient.prototype.handle_reply = function (reply, command) {
|
RedisClient.prototype.handle_reply = function (reply, command) {
|
||||||
@@ -248,57 +258,26 @@ RedisClient.prototype.on_error = function (err) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var noPasswordIsSet = /no password is set/;
|
var noPasswordIsSet = /no password is set/;
|
||||||
var loading = /LOADING/;
|
|
||||||
|
|
||||||
RedisClient.prototype.do_auth = function () {
|
RedisClient.prototype.do_auth = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
debug('Sending auth to ' + self.address + ' id ' + self.connection_id);
|
debug('Sending auth to ' + self.address + ' id ' + self.connection_id);
|
||||||
|
|
||||||
self.send_anyway = true;
|
this.send_anyway = true;
|
||||||
self.send_command('auth', [this.auth_pass], function (err, res) {
|
this.send_command('auth', [this.auth_pass], function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
/* istanbul ignore if: this is almost impossible to test */
|
if (noPasswordIsSet.test(err.message)) {
|
||||||
if (loading.test(err.message)) {
|
|
||||||
// If redis is still loading the db, it will not authenticate and everything else will fail
|
|
||||||
debug('Redis still loading, trying to authenticate later');
|
|
||||||
setTimeout(function () {
|
|
||||||
self.do_auth();
|
|
||||||
}, 333);
|
|
||||||
return;
|
|
||||||
} else if (noPasswordIsSet.test(err.message)) {
|
|
||||||
debug('Warning: Redis server does not require a password, but a password was supplied.');
|
debug('Warning: Redis server does not require a password, but a password was supplied.');
|
||||||
err = null;
|
err = null;
|
||||||
res = 'OK';
|
res = 'OK';
|
||||||
} else if (self.auth_callback) {
|
|
||||||
self.auth_callback(err);
|
|
||||||
self.auth_callback = null;
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
res = res.toString();
|
|
||||||
debug('Auth succeeded ' + self.address + ' id ' + self.connection_id);
|
|
||||||
|
|
||||||
if (self.auth_callback) {
|
|
||||||
self.auth_callback(null, res);
|
|
||||||
self.auth_callback = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we are really connected
|
|
||||||
self.emit('connect');
|
|
||||||
self.initialize_retry_vars();
|
|
||||||
|
|
||||||
if (self.options.no_ready_check) {
|
|
||||||
self.on_ready();
|
|
||||||
} else {
|
} else {
|
||||||
self.ready_check();
|
debug('Auth succeeded ' + self.address + ' id ' + self.connection_id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.send_anyway = false;
|
this.send_anyway = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
RedisClient.prototype.on_connect = function () {
|
RedisClient.prototype.on_connect = function () {
|
||||||
@@ -306,31 +285,24 @@ RedisClient.prototype.on_connect = function () {
|
|||||||
|
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
this.ready = false;
|
this.ready = false;
|
||||||
this.connections += 1;
|
|
||||||
this.emitted_end = false;
|
this.emitted_end = false;
|
||||||
if (this.options.socket_nodelay) {
|
|
||||||
this.stream.setNoDelay();
|
|
||||||
}
|
|
||||||
this.stream.setKeepAlive(this.options.socket_keepalive);
|
this.stream.setKeepAlive(this.options.socket_keepalive);
|
||||||
this.stream.setTimeout(0);
|
this.stream.setTimeout(0);
|
||||||
|
|
||||||
if (typeof this.auth_pass === 'string') {
|
this.emit('connect');
|
||||||
this.do_auth();
|
this.initialize_retry_vars();
|
||||||
} else {
|
|
||||||
this.emit('connect');
|
|
||||||
this.initialize_retry_vars();
|
|
||||||
|
|
||||||
if (this.options.no_ready_check) {
|
if (this.options.no_ready_check) {
|
||||||
this.on_ready();
|
this.on_ready();
|
||||||
} else {
|
} else {
|
||||||
this.ready_check();
|
this.ready_check();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RedisClient.prototype.on_ready = function () {
|
RedisClient.prototype.on_ready = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
debug('on_ready called ' + this.address + ' id ' + this.connection_id);
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
|
|
||||||
if (this.old_state !== null) {
|
if (this.old_state !== null) {
|
||||||
@@ -358,8 +330,8 @@ RedisClient.prototype.on_ready = function () {
|
|||||||
}
|
}
|
||||||
this.cork = cork;
|
this.cork = cork;
|
||||||
|
|
||||||
// magically restore any modal commands from a previous connection
|
// restore modal commands from previous connection
|
||||||
if (this.selected_db !== null) {
|
if (this.selected_db !== undefined) {
|
||||||
// this trick works if and only if the following send_command
|
// this trick works if and only if the following send_command
|
||||||
// never goes into the offline queue
|
// never goes into the offline queue
|
||||||
var pub_sub_mode = this.pub_sub_mode;
|
var pub_sub_mode = this.pub_sub_mode;
|
||||||
@@ -401,84 +373,43 @@ RedisClient.prototype.on_ready = function () {
|
|||||||
RedisClient.prototype.on_info_cmd = function (err, res) {
|
RedisClient.prototype.on_info_cmd = function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.message === "ERR unknown command 'info'") {
|
if (err.message === "ERR unknown command 'info'") {
|
||||||
this.server_info = {};
|
|
||||||
this.on_ready();
|
this.on_ready();
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
err.message = 'Ready check failed: ' + err.message;
|
err.message = 'Ready check failed: ' + err.message;
|
||||||
this.emit('error', err);
|
this.emit('error', err);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore if: some servers might not respond with any info data. This is just a safety check that is difficult to test */
|
/* istanbul ignore if: some servers might not respond with any info data. This is just a safety check that is difficult to test */
|
||||||
if (!res) {
|
if (!res) {
|
||||||
debug('The info command returned without any data.');
|
debug('The info command returned without any data.');
|
||||||
this.server_info = {};
|
|
||||||
this.on_ready();
|
this.on_ready();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj = {};
|
if (!this.server_info.loading || this.server_info.loading === '0') {
|
||||||
var lines = res.toString().split('\r\n');
|
|
||||||
var i = 0;
|
|
||||||
var key = 'db' + i;
|
|
||||||
var line, retry_time, parts, sub_parts;
|
|
||||||
|
|
||||||
for (i = 0; i < lines.length; i++) {
|
|
||||||
parts = lines[i].split(':');
|
|
||||||
if (parts[1]) {
|
|
||||||
obj[parts[0]] = parts[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.versions = [];
|
|
||||||
/* istanbul ignore else: some redis servers do not send the version */
|
|
||||||
if (obj.redis_version) {
|
|
||||||
obj.redis_version.split('.').forEach(function (num) {
|
|
||||||
obj.versions.push(+num);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
while (obj[key]) {
|
|
||||||
parts = obj[key].split(',');
|
|
||||||
obj[key] = {};
|
|
||||||
while (line = parts.pop()) {
|
|
||||||
sub_parts = line.split('=');
|
|
||||||
obj[key][sub_parts[0]] = +sub_parts[1];
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
key = 'db' + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose info key/vals to users
|
|
||||||
this.server_info = obj;
|
|
||||||
|
|
||||||
if (!obj.loading || obj.loading === '0') {
|
|
||||||
debug('Redis server ready.');
|
debug('Redis server ready.');
|
||||||
this.on_ready();
|
this.on_ready();
|
||||||
} else {
|
return;
|
||||||
retry_time = obj.loading_eta_seconds * 1000;
|
|
||||||
if (retry_time > 1000) {
|
|
||||||
retry_time = 1000;
|
|
||||||
}
|
|
||||||
debug('Redis server still loading, trying again in ' + retry_time);
|
|
||||||
setTimeout(function (self) {
|
|
||||||
self.ready_check();
|
|
||||||
}, retry_time, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var retry_time = +this.server_info.loading_eta_seconds * 1000;
|
||||||
|
if (retry_time > 1000) {
|
||||||
|
retry_time = 1000;
|
||||||
|
}
|
||||||
|
debug('Redis server still loading, trying again in ' + retry_time);
|
||||||
|
setTimeout(function (self) {
|
||||||
|
self.ready_check();
|
||||||
|
}, retry_time, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
RedisClient.prototype.ready_check = function () {
|
RedisClient.prototype.ready_check = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
debug('Checking server ready state...');
|
debug('Checking server ready state...');
|
||||||
|
|
||||||
this.send_anyway = true; // secret flag to send_command to send something even if not 'ready'
|
|
||||||
this.info(function (err, res) {
|
this.info(function (err, res) {
|
||||||
self.on_info_cmd(err, res);
|
self.on_info_cmd(err, res);
|
||||||
});
|
});
|
||||||
this.send_anyway = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RedisClient.prototype.send_offline_queue = function () {
|
RedisClient.prototype.send_offline_queue = function () {
|
||||||
@@ -531,7 +462,7 @@ RedisClient.prototype.connection_gone = function (why) {
|
|||||||
this.old_state = state;
|
this.old_state = state;
|
||||||
this.monitoring = false;
|
this.monitoring = false;
|
||||||
this.pub_sub_mode = false;
|
this.pub_sub_mode = false;
|
||||||
this.selected_db = null;
|
this.selected_db = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// since we are collapsing end and close, users don't expect to be called twice
|
// since we are collapsing end and close, users don't expect to be called twice
|
||||||
@@ -1010,6 +941,53 @@ RedisClient.prototype.select = RedisClient.prototype.SELECT = function (db, call
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Store db in this.select_db to restore it on reconnect
|
||||||
|
RedisClient.prototype.info = RedisClient.prototype.INFO = function (callback) {
|
||||||
|
var self = this;
|
||||||
|
this.send_anyway = true;
|
||||||
|
var tmp = this.send_command('info', [], function (err, res) {
|
||||||
|
if (res) {
|
||||||
|
var obj = {};
|
||||||
|
var lines = res.toString().split('\r\n');
|
||||||
|
var line, parts, sub_parts;
|
||||||
|
|
||||||
|
for (var i = 0; i < lines.length; i++) {
|
||||||
|
parts = lines[i].split(':');
|
||||||
|
if (parts[1]) {
|
||||||
|
if (parts[0].indexOf('db') === 0) {
|
||||||
|
sub_parts = parts[1].split(',');
|
||||||
|
obj[parts[0]] = {};
|
||||||
|
while (line = sub_parts.pop()) {
|
||||||
|
line = line.split('=');
|
||||||
|
obj[parts[0]][line[0]] = +line[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj[parts[0]] = parts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj.versions = [];
|
||||||
|
/* istanbul ignore else: some redis servers do not send the version */
|
||||||
|
if (obj.redis_version) {
|
||||||
|
obj.redis_version.split('.').forEach(function (num) {
|
||||||
|
obj.versions.push(+num);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Expose info key/vals to users
|
||||||
|
self.server_info = obj;
|
||||||
|
} else {
|
||||||
|
self.server_info = {};
|
||||||
|
}
|
||||||
|
if (typeof callback === 'function') {
|
||||||
|
callback(err, res);
|
||||||
|
} else if (err) {
|
||||||
|
self.emit('error', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.send_anyway = false;
|
||||||
|
return tmp;
|
||||||
|
};
|
||||||
|
|
||||||
RedisClient.prototype.callback_emit_error = function (callback, err) {
|
RedisClient.prototype.callback_emit_error = function (callback, err) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
setImmediate(function () {
|
setImmediate(function () {
|
||||||
@@ -1030,12 +1008,10 @@ RedisClient.prototype.auth = RedisClient.prototype.AUTH = function (pass, callba
|
|||||||
}
|
}
|
||||||
this.auth_pass = pass;
|
this.auth_pass = pass;
|
||||||
debug('Saving auth as ' + this.auth_pass);
|
debug('Saving auth as ' + this.auth_pass);
|
||||||
// Only run the callback once. So do not safe it if already connected
|
this.send_anyway = true;
|
||||||
if (this.connected) {
|
var tmp = this.send_command('auth', [pass], callback);
|
||||||
return this.send_command('auth', [this.auth_pass], callback);
|
this.send_anyway = false;
|
||||||
}
|
return tmp;
|
||||||
this.auth_callback = callback;
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RedisClient.prototype.hmset = RedisClient.prototype.HMSET = function (key, args, callback) {
|
RedisClient.prototype.hmset = RedisClient.prototype.HMSET = function (key, args, callback) {
|
||||||
|
Reference in New Issue
Block a user