You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-04 15:02:09 +03:00
Add magical auth command.
Authentication is now remembered by the client and will be automatically sent to the server on every connection, including any reconnections.
This commit is contained in:
@@ -181,6 +181,13 @@ objects instead of JavaScript Strings.
|
||||
|
||||
`createClient()` returns a `RedisClient` object that is named `client` in all of the examples here.
|
||||
|
||||
## client.auth(password, callback)
|
||||
|
||||
When connecting to Redis servers that require authentication, the `AUTH` command must be sent as the
|
||||
first command after connecting. This can be tricky to coordinate with reconnections, the ready check,
|
||||
etc. To make this easier, `client.auth()` stashes `password` and will send it after each connection,
|
||||
including reconnections. `callback` is invoked only once, after the response to the very first
|
||||
`AUTH` command sent.
|
||||
|
||||
## client.end()
|
||||
|
||||
|
@@ -1,6 +1,13 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
## v0.5.7 - February 27, 2011
|
||||
|
||||
Add magical auth command.
|
||||
|
||||
Authentication is now remembered by the client and will be automatically sent to the server
|
||||
on every connection, including any reconnections.
|
||||
|
||||
## v0.5.6 - February 22, 2011
|
||||
|
||||
Fix bug in ready check with `return_buffers` set to `true`.
|
||||
|
@@ -1,13 +1,5 @@
|
||||
// Note - Eventually this functionality will be built in to the client library
|
||||
|
||||
var redis = require("redis"),
|
||||
client = redis.createClient();
|
||||
|
||||
// whenever the client connects, make sure to auth
|
||||
client.on("connect", function () {
|
||||
client.auth("somepass", redis.print);
|
||||
});
|
||||
|
||||
// This command is magical. Client stashes the password and will issue on every connect.
|
||||
client.auth("somepass");
|
||||
|
||||
// then do whatever you want
|
||||
|
@@ -30,10 +30,9 @@ client1.on("message", function (channel, message) {
|
||||
}
|
||||
});
|
||||
|
||||
client1.incr("did a thing");
|
||||
|
||||
client1.on("ready", function () {
|
||||
// if you need auth, do it here
|
||||
client1.incr("did a thing");
|
||||
client1.subscribe("a nice channel", "another one");
|
||||
});
|
||||
|
||||
|
98
index.js
98
index.js
@@ -50,6 +50,7 @@ function RedisClient(stream, options) {
|
||||
this.subscriptions = false;
|
||||
this.closing = false;
|
||||
this.server_info = {};
|
||||
this.auth_pass = null;
|
||||
|
||||
var parser_module, self = this;
|
||||
|
||||
@@ -90,28 +91,7 @@ function RedisClient(stream, options) {
|
||||
});
|
||||
|
||||
this.stream.on("connect", function () {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Stream connected fd " + self.stream.fd);
|
||||
}
|
||||
self.connected = true;
|
||||
self.ready = false;
|
||||
self.connections += 1;
|
||||
self.command_queue = new Queue();
|
||||
self.emitted_end = false;
|
||||
|
||||
self.retry_timer = null;
|
||||
self.retry_delay = 250;
|
||||
self.stream.setNoDelay();
|
||||
self.stream.setTimeout(0);
|
||||
|
||||
self.emit("connect");
|
||||
|
||||
if (self.options.no_ready_check) {
|
||||
self.ready = true;
|
||||
self.send_offline_queue();
|
||||
} else {
|
||||
self.ready_check();
|
||||
}
|
||||
self.on_connect();
|
||||
});
|
||||
|
||||
this.stream.on("data", function (buffer_from_socket) {
|
||||
@@ -164,6 +144,55 @@ function RedisClient(stream, options) {
|
||||
util.inherits(RedisClient, events.EventEmitter);
|
||||
exports.RedisClient = RedisClient;
|
||||
|
||||
RedisClient.prototype.on_connect = function () {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Stream connected " + this.host + ":" + this.port + " fd " + this.stream.fd);
|
||||
}
|
||||
var self = this;
|
||||
|
||||
this.connected = true;
|
||||
this.ready = false;
|
||||
this.connections += 1;
|
||||
this.command_queue = new Queue();
|
||||
this.emitted_end = false;
|
||||
this.retry_timer = null;
|
||||
this.retry_delay = 250;
|
||||
this.stream.setNoDelay();
|
||||
this.stream.setTimeout(0);
|
||||
|
||||
if (this.auth_pass) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("Sending auth to " + this.host + ":" + this.port + " fd " + this.stream.fd);
|
||||
}
|
||||
self.send_anyway = true;
|
||||
self.send_command("auth", this.auth_pass, function (err, res) {
|
||||
if (err) {
|
||||
return self.emit("error", "Auth error: " + err);
|
||||
}
|
||||
if (res.toString() !== "OK") {
|
||||
return self.emit("error", "Auth failed: " + res.toString());
|
||||
}
|
||||
if (exports.debug_mode) {
|
||||
console.log("Auth succeeded " + self.host + ":" + self.port + " fd " + self.stream.fd);
|
||||
}
|
||||
if (self.auth_callback) {
|
||||
self.auth_callback(err, res);
|
||||
self.auth_callback = null;
|
||||
}
|
||||
});
|
||||
self.send_anyway = false;
|
||||
}
|
||||
|
||||
this.emit("connect");
|
||||
|
||||
if (this.options.no_ready_check) {
|
||||
this.ready = true;
|
||||
this.send_offline_queue();
|
||||
} else {
|
||||
this.ready_check();
|
||||
}
|
||||
};
|
||||
|
||||
RedisClient.prototype.ready_check = function () {
|
||||
var self = this;
|
||||
|
||||
@@ -175,8 +204,7 @@ RedisClient.prototype.ready_check = function () {
|
||||
self.send_anyway = true; // secret flag to send_command to send something even if not "ready"
|
||||
self.info(function (err, res) {
|
||||
if (err) {
|
||||
self.emit("error", "Ready check failed: " + err);
|
||||
return;
|
||||
return self.emit("error", "Ready check failed: " + err);
|
||||
}
|
||||
|
||||
var lines = res.toString().split("\r\n"), obj = {}, retry_time;
|
||||
@@ -291,7 +319,7 @@ RedisClient.prototype.connection_gone = function (why) {
|
||||
|
||||
RedisClient.prototype.on_data = function (data) {
|
||||
if (exports.debug_mode) {
|
||||
console.log("net read fd " + this.stream.fd + ": " + data.toString());
|
||||
console.log("net read " + this.host + ":" + this.port + " fd " + this.stream.fd + ": " + data.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -480,7 +508,7 @@ RedisClient.prototype.send_command = function () {
|
||||
command_str += "$" + Buffer.byteLength(arg) + "\r\n" + arg + "\r\n";
|
||||
}
|
||||
if (exports.debug_mode) {
|
||||
console.log("send fd " + this.stream.fd + ": " + command_str);
|
||||
console.log("send " + this.host + ":" + this.port + " fd " + this.stream.fd + ": " + command_str);
|
||||
}
|
||||
stream.write(command_str);
|
||||
} else {
|
||||
@@ -547,7 +575,7 @@ function Multi(client, args) {
|
||||
//bit commands
|
||||
"getbit", "setbit", "getrange", "setrange",
|
||||
// misc
|
||||
"getset", "mset", "msetnx", "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "auth", "ping", "echo",
|
||||
"getset", "mset", "msetnx", "randomkey", "select", "move", "rename", "renamenx", "expire", "expireat", "keys", "dbsize", "ping", "echo",
|
||||
"save", "bgsave", "bgwriteaof", "shutdown", "lastsave", "type", "sync", "flushdb", "flushall", "sort", "info",
|
||||
"monitor", "ttl", "persist", "slaveof", "debug", "config", "subscribe", "unsubscribe", "psubscribe", "punsubscribe", "publish", "watch", "unwatch",
|
||||
"quit"
|
||||
@@ -568,6 +596,22 @@ function Multi(client, args) {
|
||||
Multi.prototype[command.toUpperCase()] = Multi.prototype[command];
|
||||
});
|
||||
|
||||
// Stash auth for connect and reconnect. Send immediately if already connected.
|
||||
RedisClient.prototype.auth = function () {
|
||||
var args = to_array(arguments);
|
||||
this.auth_pass = args[0];
|
||||
this.auth_callback = args[1];
|
||||
if (exports.debug_mode) {
|
||||
console.log("Saving auth as " + this.auth_pass);
|
||||
}
|
||||
|
||||
if (this.connected) {
|
||||
args.unshift("auth");
|
||||
this.send_command.apply(this, args);
|
||||
}
|
||||
};
|
||||
RedisClient.prototype.AUTH = RedisClient.prototype.auth;
|
||||
|
||||
RedisClient.prototype.hmset = function () {
|
||||
var args = to_array(arguments), tmp_args;
|
||||
if (args.length >= 2 && typeof args[0] === "string" && typeof args[1] === "object") {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{ "name" : "redis",
|
||||
"version" : "0.5.6",
|
||||
"version" : "0.5.7",
|
||||
"description" : "Redis client library",
|
||||
"author": "Matt Ranney <mjr@ranney.com>",
|
||||
"contributors": [
|
||||
|
10
test.js
10
test.js
@@ -3,6 +3,7 @@ var redis = require("./index"),
|
||||
client = redis.createClient(),
|
||||
client2 = redis.createClient(),
|
||||
client3 = redis.createClient(),
|
||||
client4 = redis.createClient(9006, "filefish.redistogo.com"),
|
||||
assert = require("assert"),
|
||||
util = require("./lib/util").util,
|
||||
test_db_num = 15, // this DB will be flushed and used for testing
|
||||
@@ -1049,6 +1050,7 @@ function run_next_test() {
|
||||
console.log('\n completed \x1b[32m%d\x1b[0m tests in \x1b[33m%d\x1b[0m ms\n', test_count, new Date() - all_start);
|
||||
client.quit();
|
||||
client2.quit();
|
||||
client4.quit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1066,6 +1068,14 @@ client.on('end', function () {
|
||||
ended = true;
|
||||
});
|
||||
|
||||
// TODO - need a better way to test auth, maybe auto-config a local Redis server?
|
||||
client4.auth("664b1b6aaf134e1ec281945a8de702a9", function (err, res) {
|
||||
if (err) {
|
||||
assert.fail(err, name);
|
||||
}
|
||||
assert.strictEqual("OK", res.toString(), "auth");
|
||||
});
|
||||
|
||||
// Exit immediately on connection failure, which triggers "exit", below, which fails the test
|
||||
client.on("error", function (err) {
|
||||
console.error("client: " + err.stack);
|
||||
|
Reference in New Issue
Block a user