From cfe82331f92a0872f3032f19b305d1d8748c2fa4 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:40:52 +0100 Subject: [PATCH 01/13] Deprecate in config.hpp --- include/boost/redis/config.hpp | 47 +++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/include/boost/redis/config.hpp b/include/boost/redis/config.hpp index 4e9806794..98bb76247 100644 --- a/include/boost/redis/config.hpp +++ b/include/boost/redis/config.hpp @@ -164,7 +164,7 @@ struct config { */ std::string unix_socket; - /** @brief Username used for authentication during connection establishment. + /** @brief (Deprecated) Username used for authentication during connection establishment. * * If @ref use_setup is false (the default), during connection establishment, * authentication is performed by sending a `HELLO` command. @@ -176,10 +176,20 @@ struct config { * * When using Sentinel, this setting applies to masters and replicas. * Use @ref sentinel_config::setup to configure authorization for Sentinels. + * + * @par Deprecated + * This setting is deprecated and will be removed in a subsequent release. + * Please set @ref setup, instead: + * + * @code + * cfg.use_setup = true; + * cfg.setup.clear(); + * cfg.setup.hello("my_username", "my_password"); + * @endcode */ std::string username = "default"; - /** @brief Password used for authentication during connection establishment. + /** @brief (Deprecated) Password used for authentication during connection establishment. * * If @ref use_setup is false (the default), during connection establishment, * authentication is performed by sending a `HELLO` command. @@ -191,10 +201,20 @@ struct config { * * When using Sentinel, this setting applies to masters and replicas. * Use @ref sentinel_config::setup to configure authorization for Sentinels. + * + * @par Deprecated + * This setting is deprecated and will be removed in a subsequent release. + * Please set @ref setup, instead: + * + * @code + * cfg.use_setup = true; + * cfg.setup.clear(); + * cfg.setup.hello("my_username", "my_password"); + * @endcode */ std::string password; - /** @brief Client name parameter to use during connection establishment. + /** @brief (Deprecated) Client name parameter to use during connection establishment. * * If @ref use_setup is false (the default), during connection establishment, * a `HELLO` command is sent. If this field is not empty, the `HELLO` command @@ -202,10 +222,20 @@ struct config { * * When using Sentinel, this setting applies to masters and replicas. * Use @ref sentinel_config::setup to configure this value for Sentinels. + * + * @par Deprecated + * This setting is deprecated and will be removed in a subsequent release. + * Please set @ref setup, instead: + * + * @code + * cfg.use_setup = true; + * cfg.setup.clear(); + * cfg.setup.hello_setname("my_client_name"); + * @endcode */ std::string clientname = "Boost.Redis"; - /** @brief Database index to pass to the `SELECT` command during connection establishment. + /** @brief (Deprecated) Database index to pass to the `SELECT` command during connection establishment. * * If @ref use_setup is false (the default), and this field is set to a * non-empty optional, and its value is different than zero, @@ -213,6 +243,15 @@ struct config { * database index. By default, no `SELECT` command is sent. * * When using Sentinel, this setting applies to masters and replicas. + * + * @par Deprecated + * This setting is deprecated and will be removed in a subsequent release. + * Please set @ref setup, instead: + * + * @code + * cfg.use_setup = true; + * cfg.setup.push("SELECT", 4); // select database index 4 + * @endcode */ std::optional database_index = 0; From 2d42cce9e11fd6b1d631ab020898e5d3be56d7eb Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:41:17 +0100 Subject: [PATCH 02/13] request::hello impl --- include/boost/redis/impl/request.ipp | 2 +- include/boost/redis/request.hpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/boost/redis/impl/request.ipp b/include/boost/redis/impl/request.ipp index 72653897b..414193bd3 100644 --- a/include/boost/redis/impl/request.ipp +++ b/include/boost/redis/impl/request.ipp @@ -28,7 +28,7 @@ auto has_response(std::string_view cmd) -> bool request make_hello_request() { request req; - req.push("HELLO", "3"); + req.hello(); return req; } diff --git a/include/boost/redis/request.hpp b/include/boost/redis/request.hpp index d3104a785..c74df619c 100644 --- a/include/boost/redis/request.hpp +++ b/include/boost/redis/request.hpp @@ -724,6 +724,23 @@ class request { patterns_end); } + void hello() { push("HELLO", 3); } + + void hello(std::string_view username, std::string_view password) + { + push("HELLO", 3, "AUTH", username, password); + } + + void hello_setname(std::string_view client_name) { push("HELLO", 3, "SETNAME", client_name); } + + void hello_setname( + std::string_view username, + std::string_view password, + std::string_view client_name) + { + push("HELLO", 3, "AUTH", username, password, "SETNAME", client_name); + } + private: void check_cmd(std::string_view cmd) { From 085754bd94cc4abe323bf6a752290681ba68e6f5 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:41:23 +0100 Subject: [PATCH 03/13] Basic page --- doc/modules/ROOT/pages/auth.adoc | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 doc/modules/ROOT/pages/auth.adoc diff --git a/doc/modules/ROOT/pages/auth.adoc b/doc/modules/ROOT/pages/auth.adoc new file mode 100644 index 000000000..d138c08c4 --- /dev/null +++ b/doc/modules/ROOT/pages/auth.adoc @@ -0,0 +1,38 @@ +// +// Copyright (c) 2026 Marcelo Zimbres Silva (mzimbres@gmail.com), +// Ruben Perez Hidalgo (rubenperez038 at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + += Authentication + +If your server needs authentication, you can use setup requests: + +``` +config cfg; +cfg.use_setup = true; // required for backwards compatibility +cfg.setup.clear(); // by default, setup contains a HELLO 3. Remove it +cfg.setup.hello("my_username", "my_password"); // Replace it by a HELLO 3 with an AUTH clause + +// run normally +conn.async_run(cfg, asio::detached); + +``` + +cfg.setup contains a request that is executed every time a connection to +the server is established. + +Authentication is only a particular instance of what this mechanism can achieve. +Any other command that sets up the connection might be included here. +For example, to select a database index (TODO: link to the command) + +``` +config cfg; +cfg.use_setup = true; +cfg.push("SELECT", 42); +``` + + + From 927b070efff7effb32966964bce7c9ccdeaa950f Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:50:24 +0100 Subject: [PATCH 04/13] Properly phrase auth.adoc --- doc/modules/ROOT/pages/auth.adoc | 49 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/doc/modules/ROOT/pages/auth.adoc b/doc/modules/ROOT/pages/auth.adoc index d138c08c4..afe908ae0 100644 --- a/doc/modules/ROOT/pages/auth.adoc +++ b/doc/modules/ROOT/pages/auth.adoc @@ -8,31 +8,42 @@ = Authentication -If your server needs authentication, you can use setup requests: - -``` +Boost.Redis supports connecting to servers that require authentication. +To achieve it, you must send a +https://redis.io/commands/hello/[HELLO] command with the appropriate +`AUTH` parameters during connection establishment. Boost.Redis allows you +to customize this handshake by using a _setup request_: a request that +is run automatically before any other request, +every time a physical connection to the server is established. + +Configuration is done on xref:reference:boost/redis/config.adoc[`config`]. +Set `use_setup` to `true` (required for backwards compatibility) +and build the desired setup request in +`config::setup`. By default, the library sends a plain `HELLO 3` (RESP3 +without auth). To authenticate, clear the default setup and push a +`HELLO` command that includes your credentials: + +[source,cpp] +---- config cfg; -cfg.use_setup = true; // required for backwards compatibility -cfg.setup.clear(); // by default, setup contains a HELLO 3. Remove it -cfg.setup.hello("my_username", "my_password"); // Replace it by a HELLO 3 with an AUTH clause +cfg.use_setup = true; +cfg.setup.clear(); // Remove the default HELLO 3 +cfg.setup.hello("my_username", "my_password"); -// run normally conn.async_run(cfg, asio::detached); +---- -``` - -cfg.setup contains a request that is executed every time a connection to -the server is established. +Authentication is just one use of this mechanism. +For example, to select a particular logical database (see the Redis +https://redis.io/commands/select/[SELECT] command), add a `SELECT` +command after the `HELLO`: -Authentication is only a particular instance of what this mechanism can achieve. -Any other command that sets up the connection might be included here. -For example, to select a database index (TODO: link to the command) - -``` +[source,cpp] +---- config cfg; cfg.use_setup = true; -cfg.push("SELECT", 42); -``` - +cfg.setup.push("SELECT", 42); // select the logical database 42 after the default HELLO 3 +conn.async_run(cfg, asio::detached); +---- From 04fd1bd84db10604c942f2e677b0bb37f934c66f Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:52:19 +0100 Subject: [PATCH 05/13] Move to ipp --- include/boost/redis/impl/request.ipp | 23 +++++++++++++++++++++++ include/boost/redis/request.hpp | 14 ++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/boost/redis/impl/request.ipp b/include/boost/redis/impl/request.ipp index 414193bd3..7045a7856 100644 --- a/include/boost/redis/impl/request.ipp +++ b/include/boost/redis/impl/request.ipp @@ -65,3 +65,26 @@ void boost::redis::request::add_pubsub_arg(detail::pubsub_change_type type, std: std::size_t offset = payload_.size() - value.size() - 2u; pubsub_changes_.push_back({type, offset, value.size()}); } + +void boost::redis::request::hello() +{ + push("HELLO", 3); +} + +void boost::redis::request::hello(std::string_view username, std::string_view password) +{ + push("HELLO", 3, "AUTH", username, password); +} + +void boost::redis::request::hello_setname(std::string_view client_name) +{ + push("HELLO", 3, "SETNAME", client_name); +} + +void boost::redis::request::hello_setname( + std::string_view username, + std::string_view password, + std::string_view client_name) +{ + push("HELLO", 3, "AUTH", username, password, "SETNAME", client_name); +} diff --git a/include/boost/redis/request.hpp b/include/boost/redis/request.hpp index c74df619c..a75c3a544 100644 --- a/include/boost/redis/request.hpp +++ b/include/boost/redis/request.hpp @@ -724,22 +724,16 @@ class request { patterns_end); } - void hello() { push("HELLO", 3); } + void hello(); - void hello(std::string_view username, std::string_view password) - { - push("HELLO", 3, "AUTH", username, password); - } + void hello(std::string_view username, std::string_view password); - void hello_setname(std::string_view client_name) { push("HELLO", 3, "SETNAME", client_name); } + void hello_setname(std::string_view client_name); void hello_setname( std::string_view username, std::string_view password, - std::string_view client_name) - { - push("HELLO", 3, "AUTH", username, password, "SETNAME", client_name); - } + std::string_view client_name); private: void check_cmd(std::string_view cmd) From 8aa5f5124763b4fca7bcfb63d4d041917a1e3289 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:54:28 +0100 Subject: [PATCH 06/13] refactor --- include/boost/redis/impl/request.ipp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/include/boost/redis/impl/request.ipp b/include/boost/redis/impl/request.ipp index 7045a7856..e93040766 100644 --- a/include/boost/redis/impl/request.ipp +++ b/include/boost/redis/impl/request.ipp @@ -34,7 +34,9 @@ request make_hello_request() } // namespace boost::redis::detail -void boost::redis::request::append(const request& other) +namespace boost::redis { + +void request::append(const request& other) { // Remember the old payload size, to update offsets std::size_t old_offset = payload_.size(); @@ -55,7 +57,7 @@ void boost::redis::request::append(const request& other) } } -void boost::redis::request::add_pubsub_arg(detail::pubsub_change_type type, std::string_view value) +void request::add_pubsub_arg(detail::pubsub_change_type type, std::string_view value) { // Add the argument resp3::add_bulk(payload_, value); @@ -66,25 +68,24 @@ void boost::redis::request::add_pubsub_arg(detail::pubsub_change_type type, std: pubsub_changes_.push_back({type, offset, value.size()}); } -void boost::redis::request::hello() -{ - push("HELLO", 3); -} +void request::hello() { push("HELLO", 3); } -void boost::redis::request::hello(std::string_view username, std::string_view password) +void request::hello(std::string_view username, std::string_view password) { push("HELLO", 3, "AUTH", username, password); } -void boost::redis::request::hello_setname(std::string_view client_name) +void request::hello_setname(std::string_view client_name) { push("HELLO", 3, "SETNAME", client_name); } -void boost::redis::request::hello_setname( +void request::hello_setname( std::string_view username, std::string_view password, std::string_view client_name) { push("HELLO", 3, "AUTH", username, password, "SETNAME", client_name); } + +} // namespace boost::redis From 77185863b3bc1f419f072f409dedc0ab24b75f50 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 19:59:03 +0100 Subject: [PATCH 07/13] Tests --- test/test_request.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/test_request.cpp b/test/test_request.cpp index 9777e790c..a43469fbc 100644 --- a/test/test_request.cpp +++ b/test/test_request.cpp @@ -467,6 +467,42 @@ void test_mix_pubsub_regular() check_pubsub_changes(req, expected_changes); } +// --- hello --- +void test_hello() +{ + request req; + req.hello(); + BOOST_TEST_EQ(req.payload(), "*2\r\n$5\r\nHELLO\r\n$1\r\n3\r\n"); +} + +void test_hello_auth() +{ + request req; + req.hello("user", "pass"); + BOOST_TEST_EQ( + req.payload(), + "*5\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$4\r\nuser\r\n$4\r\npass\r\n"); +} + +void test_hello_setname() +{ + request req; + req.hello_setname("myclient"); + BOOST_TEST_EQ( + req.payload(), + "*4\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$7\r\nSETNAME\r\n$8\r\nmyclient\r\n"); +} + +void test_hello_setname_auth() +{ + request req; + req.hello_setname("user", "pass", "myclient"); + BOOST_TEST_EQ( + req.payload(), + "*7\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$4\r\nuser\r\n$4\r\npass\r\n" + "$7\r\nSETNAME\r\n$8\r\nmyclient\r\n"); +} + // --- append --- void test_append() { @@ -703,6 +739,11 @@ int main() test_mix_pubsub_regular(); + test_hello(); + test_hello_auth(); + test_hello_setname(); + test_hello_setname_auth(); + test_append(); test_append_no_response(); test_append_flags(); From 72420bde1de1bb7a1c024e3185daeeb6c12fe762 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 20:00:50 +0100 Subject: [PATCH 08/13] Make 3 a string --- include/boost/redis/impl/request.ipp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/redis/impl/request.ipp b/include/boost/redis/impl/request.ipp index e93040766..e00d0f76f 100644 --- a/include/boost/redis/impl/request.ipp +++ b/include/boost/redis/impl/request.ipp @@ -68,16 +68,16 @@ void request::add_pubsub_arg(detail::pubsub_change_type type, std::string_view v pubsub_changes_.push_back({type, offset, value.size()}); } -void request::hello() { push("HELLO", 3); } +void request::hello() { push("HELLO", "3"); } void request::hello(std::string_view username, std::string_view password) { - push("HELLO", 3, "AUTH", username, password); + push("HELLO", "3", "AUTH", username, password); } void request::hello_setname(std::string_view client_name) { - push("HELLO", 3, "SETNAME", client_name); + push("HELLO", "3", "SETNAME", client_name); } void request::hello_setname( @@ -85,7 +85,7 @@ void request::hello_setname( std::string_view password, std::string_view client_name) { - push("HELLO", 3, "AUTH", username, password, "SETNAME", client_name); + push("HELLO", "3", "AUTH", username, password, "SETNAME", client_name); } } // namespace boost::redis From dc0e43e05ab123a8367622016ab48e35e3d4b8aa Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 20:01:04 +0100 Subject: [PATCH 09/13] refactor setup_request_utils --- include/boost/redis/impl/setup_request_utils.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/redis/impl/setup_request_utils.hpp b/include/boost/redis/impl/setup_request_utils.hpp index 2fb0c6033..33451bae7 100644 --- a/include/boost/redis/impl/setup_request_utils.hpp +++ b/include/boost/redis/impl/setup_request_utils.hpp @@ -53,13 +53,13 @@ inline void compose_setup_request( // Gather everything we can in a HELLO command if (send_auth && send_setname) - req.push("HELLO", "3", "AUTH", cfg.username, cfg.password, "SETNAME", cfg.clientname); + req.hello_setname(cfg.username, cfg.password, cfg.clientname); else if (send_auth) - req.push("HELLO", "3", "AUTH", cfg.username, cfg.password); + req.hello(cfg.username, cfg.password); else if (send_setname) - req.push("HELLO", "3", "SETNAME", cfg.clientname); + req.hello_setname(cfg.clientname); else - req.push("HELLO", "3"); + req.hello(); // SELECT is independent of HELLO if (cfg.database_index && cfg.database_index.value() != 0) From d248be33b068b22d3e9df9a885fb72f0225613c4 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 20:09:57 +0100 Subject: [PATCH 10/13] Docs --- include/boost/redis/request.hpp | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/boost/redis/request.hpp b/include/boost/redis/request.hpp index a75c3a544..23b07660c 100644 --- a/include/boost/redis/request.hpp +++ b/include/boost/redis/request.hpp @@ -724,12 +724,46 @@ class request { patterns_end); } + /** @brief Appends a HELLO 3 command to the end of the request. + * + * Equivalent to adding the Redis command `HELLO 3`. + */ void hello(); + /** @brief Appends a HELLO 3 command with AUTH to the end of the request. + * + * Equivalent to the adding the following Redis command: + * @code + * HELLO 3 AUTH + * @endcode + * + * @param username The ACL username. + * @param password The password for the user. + */ void hello(std::string_view username, std::string_view password); + /** @brief Appends a HELLO 3 command with SETNAME to the end of the request. + * + * Equivalent to adding the following Redis command: + * @code + * HELLO 3 SETNAME client_name + * @endcode + * + * @param client_name The client name (visible in CLIENT LIST). + */ void hello_setname(std::string_view client_name); + /** @brief Appends a HELLO 3 command with AUTH and SETNAME to the end of the request. + * + * Equivalent to adding the following Redis command: + * @code + * HELLO 3 AUTH SETNAME + * @endcode + * + * @param username The ACL username. + * @param password The password for the user. + * @param client_name The client name (visible in CLIENT LIST). + */ void hello_setname( std::string_view username, std::string_view password, From 78764f408f5b33baf3b24838dceb35eabcf5cd07 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 20:13:09 +0100 Subject: [PATCH 11/13] doc fixes --- include/boost/redis/request.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/redis/request.hpp b/include/boost/redis/request.hpp index 23b07660c..c6a4ef21b 100644 --- a/include/boost/redis/request.hpp +++ b/include/boost/redis/request.hpp @@ -746,7 +746,7 @@ class request { * * Equivalent to adding the following Redis command: * @code - * HELLO 3 SETNAME client_name + * HELLO 3 SETNAME * @endcode * * @param client_name The client name (visible in CLIENT LIST). From effe8d2d6150d55a33ddeeac9d8b7d8e04c6889d Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Thu, 29 Jan 2026 20:21:02 +0100 Subject: [PATCH 12/13] minor doc fixes --- doc/modules/ROOT/nav.adoc | 1 + doc/modules/ROOT/pages/auth.adoc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index 8fd44b67f..034322e8f 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -2,6 +2,7 @@ * xref:requests_responses.adoc[] * xref:cancellation.adoc[] * xref:serialization.adoc[] +* xref:auth.adoc[] * xref:logging.adoc[] * xref:sentinel.adoc[] * xref:benchmarks.adoc[] diff --git a/doc/modules/ROOT/pages/auth.adoc b/doc/modules/ROOT/pages/auth.adoc index afe908ae0..668d66edd 100644 --- a/doc/modules/ROOT/pages/auth.adoc +++ b/doc/modules/ROOT/pages/auth.adoc @@ -12,7 +12,7 @@ Boost.Redis supports connecting to servers that require authentication. To achieve it, you must send a https://redis.io/commands/hello/[HELLO] command with the appropriate `AUTH` parameters during connection establishment. Boost.Redis allows you -to customize this handshake by using a _setup request_: a request that +to customize this handshake by using a "setup request": a request that is run automatically before any other request, every time a physical connection to the server is established. From 25088e65499507b4a849af2c5fd0a563cc8ae254 Mon Sep 17 00:00:00 2001 From: Ruben Perez Date: Fri, 30 Jan 2026 11:24:39 +0100 Subject: [PATCH 13/13] PR review --- doc/modules/ROOT/pages/auth.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/modules/ROOT/pages/auth.adoc b/doc/modules/ROOT/pages/auth.adoc index 668d66edd..59e1644fc 100644 --- a/doc/modules/ROOT/pages/auth.adoc +++ b/doc/modules/ROOT/pages/auth.adoc @@ -12,7 +12,7 @@ Boost.Redis supports connecting to servers that require authentication. To achieve it, you must send a https://redis.io/commands/hello/[HELLO] command with the appropriate `AUTH` parameters during connection establishment. Boost.Redis allows you -to customize this handshake by using a "setup request": a request that +to customize this handshake by using a _setup request_: a request that is run automatically before any other request, every time a physical connection to the server is established. @@ -30,7 +30,7 @@ cfg.use_setup = true; cfg.setup.clear(); // Remove the default HELLO 3 cfg.setup.hello("my_username", "my_password"); -conn.async_run(cfg, asio::detached); +co_await conn.async_run(cfg); ---- Authentication is just one use of this mechanism. @@ -44,6 +44,6 @@ config cfg; cfg.use_setup = true; cfg.setup.push("SELECT", 42); // select the logical database 42 after the default HELLO 3 -conn.async_run(cfg, asio::detached); +co_await conn.async_run(cfg); ----