Skip to content

Commit 5410adb

Browse files
committed
wip
1 parent 8fadbef commit 5410adb

File tree

3 files changed

+152
-62
lines changed

3 files changed

+152
-62
lines changed

auth/auth.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package auth
2+
3+
type StreamingCredentialsProvider interface {
4+
// Subscribe subscribes to the credentials provider and returns a channel that will receive updates.
5+
// The first response is blocking, then data will be pushed to the channel.
6+
Subscribe(listener CredentialsListener) (Credentials, CancelProviderFunc, error)
7+
}
8+
9+
type CancelProviderFunc func() error
10+
11+
type CredentialsListener interface {
12+
OnNext(credentials Credentials)
13+
OnError(err error)
14+
}
15+
16+
type Credentials interface {
17+
BasicAuth() (username string, password string)
18+
RawCredentials() string
19+
}
20+
21+
type basicAuth struct {
22+
username string
23+
password string
24+
}
25+
26+
func (b *basicAuth) RawCredentials() string {
27+
return b.username + ":" + b.password
28+
}
29+
30+
func (b *basicAuth) BasicAuth() (username string, password string) {
31+
return b.username, b.password
32+
}
33+
34+
func NewCredentials(username, password string) Credentials {
35+
return &basicAuth{
36+
username: username,
37+
password: password,
38+
}
39+
}

options.go

Lines changed: 83 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ type Limiter interface {
2929

3030
// Options keeps the settings to set up redis connection.
3131
type Options struct {
32-
// The network type, either tcp or unix.
33-
// Default is tcp.
32+
33+
// Network type, either tcp or unix.
34+
//
35+
// default: is tcp.
3436
Network string
35-
// host:port address.
37+
38+
// Addr is the address formated as host:port
3639
Addr string
3740

3841
// ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
@@ -42,21 +45,25 @@ type Options struct {
4245
// Network and Addr options.
4346
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
4447

45-
// Hook that is called when new connection is established.
48+
// OnConnect Hook that is called when new connection is established.
4649
OnConnect func(ctx context.Context, cn *Conn) error
4750

4851
// Protocol 2 or 3. Use the version to negotiate RESP version with redis-server.
49-
// Default is 3.
52+
//
53+
// default: 3.
5054
Protocol int
51-
// Use the specified Username to authenticate the current connection
55+
56+
// Username is used to authenticate the current connection
5257
// with one of the connections defined in the ACL list when connecting
5358
// to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
5459
Username string
55-
// Optional password. Must match the password specified in the
56-
// requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower),
60+
61+
// Password is an optional password. Must match the password specified in the
62+
// `requirepass` server configuration option (if connecting to a Redis 5.0 instance, or lower),
5763
// or the User Password when connecting to a Redis 6.0 instance, or greater,
5864
// that is using the Redis ACL system.
5965
Password string
66+
6067
// CredentialsProvider allows the username and password to be updated
6168
// before reconnecting. It should return the current username and password.
6269
CredentialsProvider func() (username string, password string)
@@ -67,94 +74,128 @@ type Options struct {
6774
// There will be a conflict between them; if CredentialsProviderContext exists, we will ignore CredentialsProvider.
6875
CredentialsProviderContext func(ctx context.Context) (username string, password string, err error)
6976

70-
// Database to be selected after connecting to the server.
77+
// DB is the database to be selected after connecting to the server.
7178
DB int
7279

73-
// Maximum number of retries before giving up.
74-
// Default is 3 retries; -1 (not 0) disables retries.
80+
// MaxRetries is the maximum number of retries before giving up.
81+
// -1 (not 0) disables retries.
82+
//
83+
// default: 3 retries
7584
MaxRetries int
76-
// Minimum backoff between each retry.
77-
// Default is 8 milliseconds; -1 disables backoff.
85+
86+
// MinRetryBackoff is the minimum backoff between each retry.
87+
// -1 disables backoff.
88+
//
89+
// default: 8 milliseconds
7890
MinRetryBackoff time.Duration
79-
// Maximum backoff between each retry.
80-
// Default is 512 milliseconds; -1 disables backoff.
91+
92+
// MaxRetryBackoff is the maximum backoff between each retry.
93+
// -1 disables backoff.
94+
// default: 512 milliseconds;
8195
MaxRetryBackoff time.Duration
8296

83-
// Dial timeout for establishing new connections.
84-
// Default is 5 seconds.
97+
// DialTimeout for establishing new connections.
98+
//
99+
// default: 5 seconds
85100
DialTimeout time.Duration
86-
// Timeout for socket reads. If reached, commands will fail
101+
102+
// ReadTimeout for socket reads. If reached, commands will fail
87103
// with a timeout instead of blocking. Supported values:
88-
// - `0` - default timeout (3 seconds).
89-
// - `-1` - no timeout (block indefinitely).
90-
// - `-2` - disables SetReadDeadline calls completely.
104+
//
105+
// - `-1` - no timeout (block indefinitely).
106+
// - `-2` - disables SetReadDeadline calls completely.
107+
//
108+
// default: 3 seconds
91109
ReadTimeout time.Duration
92-
// Timeout for socket writes. If reached, commands will fail
110+
111+
// WriteTimeout for socket writes. If reached, commands will fail
93112
// with a timeout instead of blocking. Supported values:
94-
// - `0` - default timeout (3 seconds).
95-
// - `-1` - no timeout (block indefinitely).
96-
// - `-2` - disables SetWriteDeadline calls completely.
113+
//
114+
// - `-1` - no timeout (block indefinitely).
115+
// - `-2` - disables SetWriteDeadline calls completely.
116+
//
117+
// default: 3 seconds
97118
WriteTimeout time.Duration
119+
98120
// ContextTimeoutEnabled controls whether the client respects context timeouts and deadlines.
99121
// See https://redis.uptrace.dev/guide/go-redis-debugging.html#timeouts
100122
ContextTimeoutEnabled bool
101123

102-
// Type of connection pool.
103-
// true for FIFO pool, false for LIFO pool.
124+
// PoolFIFO type of connection pool.
125+
//
126+
// - true for FIFO pool
127+
// - false for LIFO pool.
128+
//
104129
// Note that FIFO has slightly higher overhead compared to LIFO,
105130
// but it helps closing idle connections faster reducing the pool size.
106131
PoolFIFO bool
107-
// Base number of socket connections.
132+
133+
// PoolSize is the base number of socket connections.
108134
// Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS.
109135
// If there is not enough connections in the pool, new connections will be allocated in excess of PoolSize,
110136
// you can limit it through MaxActiveConns
137+
//
138+
// default: 10 * runtime.GOMAXPROCS(0)
111139
PoolSize int
112-
// Amount of time client waits for connection if all connections
140+
141+
// PoolTimeout is the amount of time client waits for connection if all connections
113142
// are busy before returning an error.
114-
// Default is ReadTimeout + 1 second.
143+
//
144+
// default: ReadTimeout + 1 second
115145
PoolTimeout time.Duration
116-
// Minimum number of idle connections which is useful when establishing
117-
// new connection is slow.
118-
// Default is 0. the idle connections are not closed by default.
146+
147+
// MinIdleConns is the minimum number of idle connections which is useful when establishing
148+
// new connection is slow. The idle connections are not closed by default.
149+
//
150+
// default: 0
119151
MinIdleConns int
120-
// Maximum number of idle connections.
121-
// Default is 0. the idle connections are not closed by default.
152+
153+
// MaxIdleConns is the maximum number of idle connections.
154+
// The idle connections are not closed by default.
155+
//
156+
// default: 0
122157
MaxIdleConns int
123-
// Maximum number of connections allocated by the pool at a given time.
158+
159+
// MaxActiveConns is the maximum number of connections allocated by the pool at a given time.
124160
// When zero, there is no limit on the number of connections in the pool.
161+
// If the pool is full, the next call to Get() will block until a connection is released.
125162
MaxActiveConns int
163+
126164
// ConnMaxIdleTime is the maximum amount of time a connection may be idle.
127165
// Should be less than server's timeout.
128166
//
129167
// Expired connections may be closed lazily before reuse.
130168
// If d <= 0, connections are not closed due to a connection's idle time.
169+
// -1 disables idle timeout check.
131170
//
132-
// Default is 30 minutes. -1 disables idle timeout check.
171+
// default: 30 minutes
133172
ConnMaxIdleTime time.Duration
173+
134174
// ConnMaxLifetime is the maximum amount of time a connection may be reused.
135175
//
136176
// Expired connections may be closed lazily before reuse.
137177
// If <= 0, connections are not closed due to a connection's age.
138178
//
139-
// Default is to not close idle connections.
179+
// default: 0
140180
ConnMaxLifetime time.Duration
141181

142-
// TLS Config to use. When set, TLS will be negotiated.
182+
// TLSConfig to use. When set, TLS will be negotiated.
143183
TLSConfig *tls.Config
144184

145185
// Limiter interface used to implement circuit breaker or rate limiter.
146186
Limiter Limiter
147187

148-
// Enables read only queries on slave/follower nodes.
188+
// readOnly enables read only queries on slave/follower nodes.
149189
readOnly bool
150190

151-
// Disable set-lib on connect. Default is false.
191+
// DisableIndentity set-lib on connect. Default is false.
152192
DisableIndentity bool
153193

154-
// Add suffix to client name. Default is empty.
194+
// IdentitySuffix - add suffix to client name.
155195
IdentitySuffix string
156196

157197
// UnstableResp3 enables Unstable mode for Redis Search module with RESP3.
198+
// When unstable mode is enabled, the client will use RESP3 protocol and only be able to use RawResult
158199
UnstableResp3 bool
159200
}
160201

redis.go

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"sync/atomic"
1010
"time"
1111

12+
"github.com/redis/go-redis/v9/auth"
1213
"github.com/redis/go-redis/v9/internal"
1314
"github.com/redis/go-redis/v9/internal/hscan"
1415
"github.com/redis/go-redis/v9/internal/pool"
@@ -282,36 +283,47 @@ func (c *baseClient) _getConn(ctx context.Context) (*pool.Conn, error) {
282283
return cn, nil
283284
}
284285

286+
func (c *baseClient) reAuth(ctx context.Context, cn *Conn, credentials auth.Credentials) error {
287+
var err error
288+
username, password := credentials.BasicAuth()
289+
if username != "" {
290+
err = cn.AuthACL(ctx, username, password).Err()
291+
} else {
292+
err = cn.Auth(ctx, password).Err()
293+
}
294+
return err
295+
}
296+
285297
func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
286298
if cn.Inited {
287299
return nil
288300
}
289-
cn.Inited = true
290301

291302
var err error
292-
username, password := c.opt.Username, c.opt.Password
293-
if c.opt.CredentialsProviderContext != nil {
294-
if username, password, err = c.opt.CredentialsProviderContext(ctx); err != nil {
295-
return err
296-
}
297-
} else if c.opt.CredentialsProvider != nil {
298-
username, password = c.opt.CredentialsProvider()
299-
}
300-
303+
cn.Inited = true
301304
connPool := pool.NewSingleConnPool(c.connPool, cn)
302305
conn := newConn(c.opt, connPool)
303306

304-
var auth bool
305307
protocol := c.opt.Protocol
306308
// By default, use RESP3 in current version.
307309
if protocol < 2 {
308310
protocol = 3
309311
}
310312

313+
var authenticated bool
314+
username, password := c.opt.Username, c.opt.Password
315+
if c.opt.CredentialsProviderContext != nil {
316+
if username, password, err = c.opt.CredentialsProviderContext(ctx); err != nil {
317+
return err
318+
}
319+
} else if c.opt.CredentialsProvider != nil {
320+
username, password = c.opt.CredentialsProvider()
321+
}
322+
311323
// for redis-server versions that do not support the HELLO command,
312324
// RESP2 will continue to be used.
313325
if err = conn.Hello(ctx, protocol, username, password, "").Err(); err == nil {
314-
auth = true
326+
authenticated = true
315327
} else if !isRedisError(err) {
316328
// When the server responds with the RESP protocol and the result is not a normal
317329
// execution result of the HELLO command, we consider it to be an indication that
@@ -323,15 +335,13 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
323335
return err
324336
}
325337

326-
_, err = conn.Pipelined(ctx, func(pipe Pipeliner) error {
327-
if !auth && password != "" {
328-
if username != "" {
329-
pipe.AuthACL(ctx, username, password)
330-
} else {
331-
pipe.Auth(ctx, password)
332-
}
338+
if !authenticated && password != "" {
339+
err = c.reAuth(ctx, conn, auth.NewCredentials(username, password))
340+
if err != nil {
341+
return err
333342
}
334-
343+
}
344+
_, err = conn.Pipelined(ctx, func(pipe Pipeliner) error {
335345
if c.opt.DB > 0 {
336346
pipe.Select(ctx, c.opt.DB)
337347
}

0 commit comments

Comments
 (0)