@@ -29,19 +29,11 @@ type Client struct {
29
29
// Dial is the function used to create new connections.
30
30
Dial func (ctx context.Context ) (net.Conn , error )
31
31
32
- // AuthUsername is the username used for authentication.
32
+ // Setup is called after a new connection is established, but before any
33
+ // commands are sent. It is useful for selecting a database or authenticating.
33
34
//
34
- // If set, AuthPassword must also be set. If not using Redis ACLs, just
35
- // set AuthPassword.
36
- //
37
- // See more: https://redis.io/commands/auth/
38
- AuthUsername string
39
- // AuthPassword is the password used for authentication.
40
- // Authentication must be set before any other commands are sent, and
41
- // must not change during the lifetime of the client.
42
- //
43
- // See more: https://redis.io/commands/auth/
44
- AuthPassword string
35
+ // See SetupAuth for authenticating with a username and password.
36
+ Setup func (ctx context.Context , client * Client , pipe * Pipeline ) error
45
37
46
38
poolMu sync.Mutex
47
39
pool * connPool
@@ -104,9 +96,8 @@ func NewFromURL(rawURL string) (*Client, error) {
104
96
}
105
97
106
98
if u .User != nil {
107
- client .AuthUsername = u .User .Username ()
108
99
pass , _ := u .User .Password ()
109
- client .AuthPassword = pass
100
+ client .Setup = SetupAuth ( u . User . Username (), pass )
110
101
}
111
102
112
103
return client , nil
@@ -164,28 +155,45 @@ func (c *Client) getConn(ctx context.Context) (*Pipeline, error) {
164
155
165
156
r := c .newResult (conn )
166
157
167
- if c .AuthUsername == "" && c .AuthPassword == "" {
168
- return r , nil
169
- }
170
-
171
- if c .AuthUsername != "" && c .AuthPassword == "" {
172
- nc .Close ()
173
- return nil , errors .New ("auth username set but password not set" )
158
+ if c .Setup != nil {
159
+ err = c .Setup (ctx , c , r )
160
+ if err != nil {
161
+ nc .Close ()
162
+ return nil , fmt .Errorf ("setup: %w" , err )
163
+ }
174
164
}
175
165
176
- if c .AuthUsername != "" {
177
- r = c .Pipeline (ctx , r , "AUTH" , c .AuthUsername , c .AuthPassword )
178
- } else {
179
- r = c .Pipeline (ctx , r , "AUTH" , c .AuthPassword )
180
- }
166
+ return r , nil
167
+ }
181
168
182
- err = r .Ok ()
183
- if err != nil {
184
- nc .Close ()
185
- return nil , fmt .Errorf ("auth: %w" , err )
169
+ // SetupAuth returns a Setup function that authenticates with the given username and password.
170
+ //
171
+ // AuthUsername is the username used for authentication.
172
+ //
173
+ // If set, AuthPassword must also be set. If not using Redis ACLs, just
174
+ // set AuthPassword.
175
+ //
176
+ // See more: https://redis.io/commands/auth/
177
+ // AuthPassword is the password used for authentication.
178
+ // Authentication must be set before any other commands are sent, and
179
+ // must not change during the lifetime of the client.
180
+ //
181
+ // See more: https://redis.io/commands/auth/
182
+ func SetupAuth (
183
+ username string ,
184
+ password string ,
185
+ ) func (ctx context.Context , client * Client , pipe * Pipeline ) error {
186
+ return func (ctx context.Context , client * Client , pipe * Pipeline ) error {
187
+ switch {
188
+ case username != "" && password != "" :
189
+ pipe = client .Pipeline (ctx , pipe , "AUTH" , username , password )
190
+ case password != "" :
191
+ pipe = client .Pipeline (ctx , pipe , "AUTH" , password )
192
+ default :
193
+ return fmt .Errorf ("username is set but password is not" )
194
+ }
195
+ return pipe .Ok ()
186
196
}
187
-
188
- return r , nil
189
197
}
190
198
191
199
func (c * Client ) putConn (conn * conn ) {
0 commit comments