This is an automated email from the ASF dual-hosted git repository.
wwbmmm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git
The following commit(s) were added to refs/heads/master by this push:
new cffbd243 keep session info in RedisConnContext (#2902)
cffbd243 is described below
commit cffbd243e5100d4b5d69bfd1b12473e7abef3993
Author: Tanghui Lin <[email protected]>
AuthorDate: Thu Mar 6 19:25:52 2025 +0800
keep session info in RedisConnContext (#2902)
* keep session info in RedisConnContext
* fix comment
* add uint test for redis ctx
* fix uinttest
---
example/BUILD.bazel | 11 +++
example/redis_c++/redis_server.cpp | 114 ++++++++++++++++++++++++++----
src/brpc/policy/redis_protocol.cpp | 34 +--------
src/brpc/redis.cpp | 17 +++++
src/brpc/redis.h | 46 ++++++++++++-
test/BUILD.bazel | 1 +
test/brpc_redis_unittest.cpp | 137 ++++++++++++++++++++++++++++++++++---
7 files changed, 305 insertions(+), 55 deletions(-)
diff --git a/example/BUILD.bazel b/example/BUILD.bazel
index b38cd5a1..df2722a4 100644
--- a/example/BUILD.bazel
+++ b/example/BUILD.bazel
@@ -123,3 +123,14 @@ cc_binary(
"//:brpc",
],
)
+
+cc_binary(
+ name = "redis_c++_server",
+ srcs = [
+ "redis_c++/redis_server.cpp",
+ ],
+ copts = COPTS,
+ deps = [
+ "//:brpc",
+ ],
+)
\ No newline at end of file
diff --git a/example/redis_c++/redis_server.cpp
b/example/redis_c++/redis_server.cpp
index 6ebc3853..a53ee26e 100644
--- a/example/redis_c++/redis_server.cpp
+++ b/example/redis_c++/redis_server.cpp
@@ -31,21 +31,54 @@
DEFINE_int32(port, 6379, "TCP Port of this server");
+class AuthSession : public brpc::Destroyable {
+public:
+ explicit AuthSession(const std::string& user_name, const std::string&
password)
+ : _user_name(user_name), _password(password) {}
+
+ void Destroy() override {
+ delete this;
+ }
+
+ const std::string _user_name;
+ const std::string _password;
+};
+
class RedisServiceImpl : public brpc::RedisService {
public:
- bool Set(const std::string& key, const std::string& value) {
+ RedisServiceImpl() {
+ _user_password["db1"] = "123456";
+ _user_password["db2"] = "123456";
+ _db_map["db1"].resize(kHashSlotNum);
+ _db_map["db2"].resize(kHashSlotNum);
+ }
+
+ bool Set(const std::string& db_name, const std::string& key, const
std::string& value) {
int slot = butil::crc32c::Value(key.c_str(), key.size()) %
kHashSlotNum;
_mutex[slot].lock();
- _map[slot][key] = value;
+ auto& kv = _db_map[db_name];
+ kv[slot][key] = value;
_mutex[slot].unlock();
return true;
}
- bool Get(const std::string& key, std::string* value) {
+ bool Auth(const std::string& db_name, const std::string& password) {
+ if (_user_password.find(db_name) == _user_password.end()) {
+ return false;
+ } else {
+ if (_user_password[db_name] != password) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool Get(const std::string& db_name, const std::string& key, std::string*
value) {
int slot = butil::crc32c::Value(key.c_str(), key.size()) %
kHashSlotNum;
_mutex[slot].lock();
- auto it = _map[slot].find(key);
- if (it == _map[slot].end()) {
+ auto& kv = _db_map[db_name];
+ auto it = kv[slot].find(key);
+ if (it == kv[slot].end()) {
_mutex[slot].unlock();
return false;
}
@@ -56,7 +89,9 @@ public:
private:
const static int kHashSlotNum = 32;
- std::unordered_map<std::string, std::string> _map[kHashSlotNum];
+ typedef std::unordered_map<std::string, std::string> KVStore;
+ std::unordered_map<std::string, std::vector<KVStore>> _db_map;
+ std::unordered_map<std::string, std::string> _user_password;
butil::Mutex _mutex[kHashSlotNum];
};
@@ -65,16 +100,27 @@ public:
explicit GetCommandHandler(RedisServiceImpl* rsimpl)
: _rsimpl(rsimpl) {}
- brpc::RedisCommandHandlerResult Run(const std::vector<butil::StringPiece>&
args,
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
brpc::RedisReply* output,
bool /*flush_batched*/) override {
+
+ AuthSession* session = static_cast<AuthSession*>(ctx->get_session());
+ if (session == nullptr) {
+ output->FormatError("No auth session");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ if (session->_user_name.empty()) {
+ output->FormatError("No user name");
+ return brpc::REDIS_CMD_HANDLED;
+ }
if (args.size() != 2ul) {
output->FormatError("Expect 1 arg for 'get', actually %lu",
args.size()-1);
return brpc::REDIS_CMD_HANDLED;
}
const std::string key(args[1].data(), args[1].size());
std::string value;
- if (_rsimpl->Get(key, &value)) {
+ if (_rsimpl->Get(session->_user_name, key, &value)) {
output->SetString(value);
} else {
output->SetNullString();
@@ -91,22 +137,64 @@ public:
explicit SetCommandHandler(RedisServiceImpl* rsimpl)
: _rsimpl(rsimpl) {}
- brpc::RedisCommandHandlerResult Run(const std::vector<butil::StringPiece>&
args,
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
brpc::RedisReply* output,
bool /*flush_batched*/) override {
+ AuthSession* session = static_cast<AuthSession*>(ctx->get_session());
+ if (session == nullptr) {
+ output->FormatError("No auth session");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ if (session->_user_name.empty()) {
+ output->FormatError("No user name");
+ return brpc::REDIS_CMD_HANDLED;
+ }
if (args.size() != 3ul) {
output->FormatError("Expect 2 args for 'set', actually %lu",
args.size()-1);
return brpc::REDIS_CMD_HANDLED;
}
const std::string key(args[1].data(), args[1].size());
const std::string value(args[2].data(), args[2].size());
- _rsimpl->Set(key, value);
+ _rsimpl->Set(session->_user_name, key, value);
output->SetStatus("OK");
return brpc::REDIS_CMD_HANDLED;
}
private:
- RedisServiceImpl* _rsimpl;
+ RedisServiceImpl* _rsimpl;
+};
+
+
+
+class AuthCommandHandler : public brpc::RedisCommandHandler {
+public:
+ explicit AuthCommandHandler(RedisServiceImpl* rsimpl)
+ : _rsimpl(rsimpl) {}
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
+ brpc::RedisReply* output,
+ bool /*flush_batched*/) override {
+ if (args.size() != 3ul) {
+ output->FormatError("Expect 2 args for 'auth', actually %lu",
args.size()-1);
+ return brpc::REDIS_CMD_HANDLED;
+ }
+
+ const std::string db_name(args[1].data(), args[1].size());
+ const std::string password(args[2].data(), args[2].size());
+
+ if (_rsimpl->Auth(db_name, password)) {
+ output->SetStatus("OK");
+ auto auth_session = new AuthSession(db_name, password);
+ ctx->reset_session(auth_session);
+ } else {
+ output->FormatError("Invalid password for database '%s'",
db_name.c_str());
+ }
+ return brpc::REDIS_CMD_HANDLED;
+ }
+
+private:
+ RedisServiceImpl* _rsimpl;
};
int main(int argc, char* argv[]) {
@@ -114,9 +202,11 @@ int main(int argc, char* argv[]) {
RedisServiceImpl *rsimpl = new RedisServiceImpl;
auto get_handler =std::unique_ptr<GetCommandHandler>(new
GetCommandHandler(rsimpl));
auto set_handler =std::unique_ptr<SetCommandHandler>( new
SetCommandHandler(rsimpl));
+ auto auth_handler = std::unique_ptr<AuthCommandHandler>(new
AuthCommandHandler(rsimpl));
rsimpl->AddCommandHandler("get", get_handler.get());
rsimpl->AddCommandHandler("set", set_handler.get());
-
+ rsimpl->AddCommandHandler("auth", auth_handler.get());
+
brpc::Server server;
brpc::ServerOptions server_options;
server_options.redis_service = rsimpl;
diff --git a/src/brpc/policy/redis_protocol.cpp
b/src/brpc/policy/redis_protocol.cpp
index 94524e8b..f8acf49d 100644
--- a/src/brpc/policy/redis_protocol.cpp
+++ b/src/brpc/policy/redis_protocol.cpp
@@ -54,27 +54,6 @@ struct InputResponse : public InputMessageBase {
}
};
-// This class is as parsing_context in socket.
-class RedisConnContext : public Destroyable {
-public:
- explicit RedisConnContext(const RedisService* rs)
- : redis_service(rs)
- , batched_size(0) {}
-
- ~RedisConnContext();
- // @Destroyable
- void Destroy() override;
-
- const RedisService* redis_service;
- // If user starts a transaction, transaction_handler indicates the
- // handler pointer that runs the transaction command.
- std::unique_ptr<RedisCommandHandler> transaction_handler;
- // >0 if command handler is run in batched mode.
- int batched_size;
-
- RedisCommandParser parser;
- butil::Arena arena;
-};
int ConsumeCommand(RedisConnContext* ctx,
const std::vector<butil::StringPiece>& args,
@@ -83,7 +62,7 @@ int ConsumeCommand(RedisConnContext* ctx,
RedisReply output(&ctx->arena);
RedisCommandHandlerResult result = REDIS_CMD_HANDLED;
if (ctx->transaction_handler) {
- result = ctx->transaction_handler->Run(args, &output, flush_batched);
+ result = ctx->transaction_handler->Run(ctx, args, &output,
flush_batched);
if (result == REDIS_CMD_HANDLED) {
ctx->transaction_handler.reset(NULL);
} else if (result == REDIS_CMD_BATCHED) {
@@ -97,7 +76,7 @@ int ConsumeCommand(RedisConnContext* ctx,
snprintf(buf, sizeof(buf), "ERR unknown command `%s`",
args[0].as_string().c_str());
output.SetError(buf);
} else {
- result = ch->Run(args, &output, flush_batched);
+ result = ch->Run(ctx, args, &output, flush_batched);
if (result == REDIS_CMD_CONTINUE) {
if (ctx->batched_size != 0) {
LOG(ERROR) << "CONTINUE should not be returned in a
batched process.";
@@ -134,15 +113,6 @@ int ConsumeCommand(RedisConnContext* ctx,
return 0;
}
-// ========== impl of RedisConnContext ==========
-
-RedisConnContext::~RedisConnContext() { }
-
-void RedisConnContext::Destroy() {
- delete this;
-}
-
-// ========== impl of RedisConnContext ==========
ParseResult ParseRedisMessage(butil::IOBuf* source, Socket* socket,
bool read_eof, const void* arg) {
diff --git a/src/brpc/redis.cpp b/src/brpc/redis.cpp
index 777e1999..f8870ae5 100644
--- a/src/brpc/redis.cpp
+++ b/src/brpc/redis.cpp
@@ -370,4 +370,21 @@ RedisCommandHandler*
RedisCommandHandler::NewTransactionHandler() {
return NULL;
}
+// ========== impl of RedisConnContext ==========
+RedisConnContext::~RedisConnContext() { }
+
+void RedisConnContext::Destroy() {
+ if (session) {
+ session->Destroy();
+ }
+ delete this;
+}
+
+void RedisConnContext::reset_session(Destroyable* s){
+ if (session) {
+ session->Destroy();
+ }
+ session = s;
+}
+
} // namespace brpc
diff --git a/src/brpc/redis.h b/src/brpc/redis.h
index c6b0ea21..50064519 100644
--- a/src/brpc/redis.h
+++ b/src/brpc/redis.h
@@ -21,8 +21,10 @@
#include <unordered_map>
+#include "brpc/destroyable.h"
#include "brpc/nonreflectable_message.h"
#include "brpc/parse_result.h"
+#include "brpc/redis_command.h"
#include "brpc/pb_compat.h"
#include "brpc/redis_reply.h"
#include "butil/arena.h"
@@ -210,6 +212,39 @@ enum RedisCommandHandlerResult {
REDIS_CMD_BATCHED = 2,
};
+class RedisCommandParser;
+
+// This class is as parsing_context in socket.
+class RedisConnContext : public Destroyable {
+public:
+ explicit RedisConnContext(const RedisService* rs)
+ : redis_service(rs)
+ , batched_size(0)
+ , session(nullptr) {}
+
+ ~RedisConnContext();
+ // @Destroyable
+ void Destroy() override;
+ void reset_session(Destroyable* s);
+
+ Destroyable* get_session() { return session; }
+
+ const RedisService* redis_service;
+ // If user starts a transaction, transaction_handler indicates the
+ // handler pointer that runs the transaction command.
+ std::unique_ptr<RedisCommandHandler> transaction_handler;
+ // >0 if command handler is run in batched mode.
+ int batched_size;
+
+ RedisCommandParser parser;
+ butil::Arena arena;
+
+private:
+ // If user is authenticated, session is set.
+ // Keep auth session info in RedisConnContext to distinguish diffrent
users( or diffrent db).
+ Destroyable* session;
+};
+
// The Command handler for a redis request. User should impletement Run().
class RedisCommandHandler {
public:
@@ -235,8 +270,15 @@ public:
// it returns REDIS_CMD_HANDLED. Read the comment below.
virtual RedisCommandHandlerResult Run(const
std::vector<butil::StringPiece>& args,
brpc::RedisReply* output,
- bool flush_batched) = 0;
-
+ bool flush_batched) {
+ return REDIS_CMD_HANDLED;
+ };
+ virtual RedisCommandHandlerResult Run(RedisConnContext* ctx,
+ const
std::vector<butil::StringPiece>& args,
+ brpc::RedisReply* output,
+ bool flush_batched) {
+ return Run(args, output, flush_batched);
+ }
// The Run() returns CONTINUE for "multi", which makes brpc call this
method to
// create a transaction_handler to process following commands until
transaction_handler
// returns OK. For example, for command "multi; set k1 v1; set k2 v2; set
k3 v3;
diff --git a/test/BUILD.bazel b/test/BUILD.bazel
index 9817b45f..1e0ef966 100644
--- a/test/BUILD.bazel
+++ b/test/BUILD.bazel
@@ -192,6 +192,7 @@ cc_test(
],
)
+
cc_test(
name = "bvar_test",
srcs = glob(
diff --git a/test/brpc_redis_unittest.cpp b/test/brpc_redis_unittest.cpp
index 573ab2ed..017d5c7e 100644
--- a/test/brpc_redis_unittest.cpp
+++ b/test/brpc_redis_unittest.cpp
@@ -811,10 +811,13 @@ butil::Mutex s_mutex;
std::unordered_map<std::string, std::string> m;
std::unordered_map<std::string, int64_t> int_map;
+
class RedisServiceImpl : public brpc::RedisService {
public:
RedisServiceImpl()
- : _batch_count(0) {}
+ : _batch_count(0)
+ , _user("user1")
+ , _password("password1") {}
brpc::RedisCommandHandlerResult OnBatched(const
std::vector<butil::StringPiece>& args,
brpc::RedisReply* output, bool flush_batched) {
@@ -864,8 +867,52 @@ public:
std::vector<std::vector<std::string> > _batched_command;
int _batch_count;
+ std::string _user;
+ std::string _password;
+};
+
+
+class AuthSession : public brpc::Destroyable {
+public:
+ explicit AuthSession(const std::string& user_name, const std::string&
password)
+ : _user_name(user_name), _password(password) {}
+
+ void Destroy() override {
+ delete this;
+ }
+
+ const std::string _user_name;
+ const std::string _password;
};
+class AuthCommandHandler : public brpc::RedisCommandHandler {
+public:
+ AuthCommandHandler(RedisServiceImpl* rs)
+ : _rs(rs) {}
+
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
+ brpc::RedisReply* output,
+ bool flush_batched) {
+ if (args.size() < 2) {
+ output->SetError("ERR wrong number of arguments for 'AUTH'
command");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ const std::string user(args[1].data(), args[1].size());
+ const std::string password(args[2].data(), args[2].size());
+ if (_rs->_user != user || _rs->_password != password) {
+ output->SetError("ERR invalid username/password");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ auto auth_session = new AuthSession(user, password);
+ ctx->reset_session(auth_session);
+ output->SetStatus("OK");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+
+private:
+ RedisServiceImpl* _rs;
+};
class SetCommandHandler : public brpc::RedisCommandHandler {
public:
@@ -873,9 +920,19 @@ public:
: _rs(rs)
, _batch_process(batch_process) {}
- brpc::RedisCommandHandlerResult Run(const std::vector<butil::StringPiece>&
args,
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
brpc::RedisReply* output,
bool flush_batched) {
+ if (!ctx->session) {
+ output->SetError("ERR no auth");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ AuthSession* session = static_cast<AuthSession*>(ctx->session);
+ if (!session || (session->_password != _rs->_password) ||
(session->_user_name != _rs->_user)) {
+ output->SetError("ERR no auth");
+ return brpc::REDIS_CMD_HANDLED;
+ }
if (args.size() < 3) {
output->SetError("ERR wrong number of arguments for 'set'
command");
return brpc::REDIS_CMD_HANDLED;
@@ -898,15 +955,26 @@ private:
bool _batch_process;
};
+
class GetCommandHandler : public brpc::RedisCommandHandler {
public:
GetCommandHandler(RedisServiceImpl* rs, bool batch_process = false)
: _rs(rs)
, _batch_process(batch_process) {}
- brpc::RedisCommandHandlerResult Run(const std::vector<butil::StringPiece>&
args,
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
brpc::RedisReply* output,
bool flush_batched) {
+ if (!ctx->session) {
+ output->SetError("ERR no auth");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ AuthSession* session = static_cast<AuthSession*>(ctx->session);
+ if (!session || (session->_password != _rs->_password) ||
(session->_user_name != _rs->_user)) {
+ output->SetError("ERR no auth");
+ return brpc::REDIS_CMD_HANDLED;
+ }
if (args.size() < 2) {
output->SetError("ERR wrong number of arguments for 'get'
command");
return brpc::REDIS_CMD_HANDLED;
@@ -935,11 +1003,22 @@ private:
class IncrCommandHandler : public brpc::RedisCommandHandler {
public:
- IncrCommandHandler() {}
+ IncrCommandHandler(RedisServiceImpl* rs)
+ : _rs(rs) {}
- brpc::RedisCommandHandlerResult Run(const std::vector<butil::StringPiece>&
args,
+ brpc::RedisCommandHandlerResult Run(brpc::RedisConnContext* ctx,
+ const std::vector<butil::StringPiece>&
args,
brpc::RedisReply* output,
bool flush_batched) {
+ if (!ctx->session) {
+ output->SetError("ERR no auth");
+ return brpc::REDIS_CMD_HANDLED;
+ }
+ AuthSession* session = static_cast<AuthSession*>(ctx->session);
+ if (!session || (session->_password != _rs->_password) ||
(session->_user_name != _rs->_user)) {
+ output->SetError("ERR no auth");
+ return brpc::REDIS_CMD_HANDLED;
+ }
if (args.size() < 2) {
output->SetError("ERR wrong number of arguments for 'incr'
command");
return brpc::REDIS_CMD_HANDLED;
@@ -951,6 +1030,9 @@ public:
output->SetInteger(value);
return brpc::REDIS_CMD_HANDLED;
}
+
+private:
+ RedisServiceImpl* _rs;
};
TEST_F(RedisTest, server_sanity) {
@@ -959,10 +1041,12 @@ TEST_F(RedisTest, server_sanity) {
RedisServiceImpl* rsimpl = new RedisServiceImpl;
GetCommandHandler *gh = new GetCommandHandler(rsimpl);
SetCommandHandler *sh = new SetCommandHandler(rsimpl);
- IncrCommandHandler *ih = new IncrCommandHandler;
+ AuthCommandHandler *ah = new AuthCommandHandler(rsimpl);
+ IncrCommandHandler *ih = new IncrCommandHandler(rsimpl);
rsimpl->AddCommandHandler("get", gh);
rsimpl->AddCommandHandler("set", sh);
rsimpl->AddCommandHandler("incr", ih);
+ rsimpl->AddCommandHandler("auth", ah);
server_options.redis_service = rsimpl;
brpc::PortRange pr(8081, 8900);
ASSERT_EQ(0, server.Start("127.0.0.1", pr, &server_options));
@@ -975,6 +1059,15 @@ TEST_F(RedisTest, server_sanity) {
brpc::RedisRequest request;
brpc::RedisResponse response;
brpc::Controller cntl;
+ ASSERT_TRUE(request.AddCommand("auth user1 password1"));
+ channel.CallMethod(NULL, &cntl, &request, &response, NULL);
+ ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText();
+ ASSERT_EQ(1, response.reply_size());
+ ASSERT_EQ(brpc::REDIS_REPLY_STATUS, response.reply(0).type());
+ ASSERT_STREQ("OK", response.reply(0).c_str());
+ request.Clear();
+ response.Clear();
+ cntl.Reset();
ASSERT_TRUE(request.AddCommand("get hello"));
ASSERT_TRUE(request.AddCommand("get hello2"));
ASSERT_TRUE(request.AddCommand("set key1 value1"));
@@ -1029,7 +1122,13 @@ TEST_F(RedisTest, server_sanity) {
void* incr_thread(void* arg) {
brpc::Channel* c = static_cast<brpc::Channel*>(arg);
-
+ // do auth
+ brpc::RedisRequest auth_req;
+ brpc::RedisResponse auth_resp;
+ brpc::Controller auth_cntl;
+ EXPECT_TRUE(auth_req.AddCommand("auth user1 password1"));
+ c->CallMethod(NULL, &auth_cntl, &auth_req, &auth_resp, NULL);
+ EXPECT_FALSE(auth_cntl.Failed()) << auth_cntl.ErrorText();
for (int i = 0; i < 5000; ++i) {
brpc::RedisRequest request;
brpc::RedisResponse response;
@@ -1048,8 +1147,10 @@ TEST_F(RedisTest, server_concurrency) {
brpc::Server server;
brpc::ServerOptions server_options;
RedisServiceImpl* rsimpl = new RedisServiceImpl;
- IncrCommandHandler *ih = new IncrCommandHandler;
+ AuthCommandHandler *ah = new AuthCommandHandler(rsimpl);
+ IncrCommandHandler *ih = new IncrCommandHandler(rsimpl);
rsimpl->AddCommandHandler("incr", ih);
+ rsimpl->AddCommandHandler("auth", ah);
server_options.redis_service = rsimpl;
brpc::PortRange pr(8081, 8900);
ASSERT_EQ(0, server.Start("0.0.0.0", pr, &server_options));
@@ -1130,9 +1231,10 @@ TEST_F(RedisTest, server_command_continue) {
brpc::Server server;
brpc::ServerOptions server_options;
RedisServiceImpl* rsimpl = new RedisServiceImpl;
+ rsimpl->AddCommandHandler("auth", new AuthCommandHandler(rsimpl));
rsimpl->AddCommandHandler("get", new GetCommandHandler(rsimpl));
rsimpl->AddCommandHandler("set", new SetCommandHandler(rsimpl));
- rsimpl->AddCommandHandler("incr", new IncrCommandHandler);
+ rsimpl->AddCommandHandler("incr", new IncrCommandHandler(rsimpl));
rsimpl->AddCommandHandler("multi", new MultiCommandHandler);
server_options.redis_service = rsimpl;
brpc::PortRange pr(8081, 8900);
@@ -1142,6 +1244,13 @@ TEST_F(RedisTest, server_command_continue) {
options.protocol = brpc::PROTOCOL_REDIS;
brpc::Channel channel;
ASSERT_EQ(0, channel.Init("127.0.0.1", server.listen_address().port,
&options));
+ // do auth
+ brpc::RedisRequest auth_req;
+ brpc::RedisResponse auth_resp;
+ brpc::Controller auth_cntl;
+ ASSERT_TRUE(auth_req.AddCommand("auth user1 password1"));
+ channel.CallMethod(NULL, &auth_cntl, &auth_req, &auth_resp, NULL);
+ ASSERT_FALSE(auth_cntl.Failed()) << auth_cntl.ErrorText();
{
brpc::RedisRequest request;
@@ -1207,6 +1316,8 @@ TEST_F(RedisTest, server_handle_pipeline) {
RedisServiceImpl* rsimpl = new RedisServiceImpl;
GetCommandHandler* getch = new GetCommandHandler(rsimpl, true);
SetCommandHandler* setch = new SetCommandHandler(rsimpl, true);
+ AuthCommandHandler* authch = new AuthCommandHandler(rsimpl);
+ rsimpl->AddCommandHandler("auth", authch);
rsimpl->AddCommandHandler("get", getch);
rsimpl->AddCommandHandler("set", setch);
rsimpl->AddCommandHandler("multi", new MultiCommandHandler);
@@ -1222,6 +1333,14 @@ TEST_F(RedisTest, server_handle_pipeline) {
brpc::RedisRequest request;
brpc::RedisResponse response;
brpc::Controller cntl;
+ ASSERT_TRUE(request.AddCommand("auth user1 password1"));
+ channel.CallMethod(NULL, &cntl, &request, &response, NULL);
+ ASSERT_FALSE(cntl.Failed()) << cntl.ErrorText();
+ ASSERT_EQ(1, response.reply_size());
+ ASSERT_STREQ("OK", response.reply(0).c_str());
+ request.Clear();
+ response.Clear();
+ cntl.Reset();
ASSERT_TRUE(request.AddCommand("set key1 v1"));
ASSERT_TRUE(request.AddCommand("set key2 v2"));
ASSERT_TRUE(request.AddCommand("set key3 v3"));
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]