Skip to content

Commit 46992b0

Browse files
authored
fix: DialURL compatibility with redis-cli (#566)
Fix compatibility of DialURL with respect for single component user-info records. This enables URLs such as redis://mypass@localhost/1 as supported by redis-cli to be used.
1 parent 72af812 commit 46992b0

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

redis/conn.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ func DialPassword(password string) DialOption {
168168

169169
// DialUsername specifies the username to use when connecting to
170170
// the Redis server when Redis ACLs are used.
171+
// A DialPassword must also be passed otherwise this option will have no effect.
171172
func DialUsername(username string) DialOption {
172173
return DialOption{func(do *dialOptions) {
173174
do.username = username
@@ -347,8 +348,18 @@ func DialURL(rawurl string, options ...DialOption) (Conn, error) {
347348

348349
if u.User != nil {
349350
password, isSet := u.User.Password()
351+
username := u.User.Username()
350352
if isSet {
351-
options = append(options, DialUsername(u.User.Username()), DialPassword(password))
353+
if username != "" {
354+
// ACL
355+
options = append(options, DialUsername(username), DialPassword(password))
356+
} else {
357+
// requirepass - user-info username:password with blank username
358+
options = append(options, DialPassword(password))
359+
}
360+
} else if username != "" {
361+
// requirepass - redis-cli compatibility which treats as single arg in user-info as a password
362+
options = append(options, DialPassword(username))
352363
}
353364
}
354365

redis/conn_test.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,13 @@ var dialURLTests = []struct {
640640
w string
641641
}{
642642
{"password", "redis://:abc123@localhost", "+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
643+
{"password redis-cli compat", "redis://abc123@localhost", "+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
644+
{"password db1", "redis://:abc123@localhost/1", "+OK\r\n+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n*2\r\n$6\r\nSELECT\r\n$1\r\n1\r\n"},
645+
{"password db1 redis-cli compat", "redis://abc123@localhost/1", "+OK\r\n+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n*2\r\n$6\r\nSELECT\r\n$1\r\n1\r\n"},
646+
{"password no host db0", "redis://:abc123@/0", "+OK\r\n+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
647+
{"password no host db0 redis-cli compat", "redis://abc123@/0", "+OK\r\n+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
648+
{"password no host db1", "redis://:abc123@/1", "+OK\r\n+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n*2\r\n$6\r\nSELECT\r\n$1\r\n1\r\n"},
649+
{"password no host db1 redis-cli compat", "redis://abc123@/1", "+OK\r\n+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n*2\r\n$6\r\nSELECT\r\n$1\r\n1\r\n"},
643650
{"username and password", "redis://user:password@localhost", "+OK\r\n", "*3\r\n$4\r\nAUTH\r\n$4\r\nuser\r\n$8\r\npassword\r\n"},
644651
{"username", "redis://x:@localhost", "+OK\r\n", ""},
645652
{"database 3", "redis://localhost/3", "+OK\r\n", "*2\r\n$6\r\nSELECT\r\n$1\r\n3\r\n"},
@@ -649,16 +656,18 @@ var dialURLTests = []struct {
649656

650657
func TestDialURL(t *testing.T) {
651658
for _, tt := range dialURLTests {
652-
var buf bytes.Buffer
653-
// UseTLS should be ignored in all of these tests.
654-
_, err := redis.DialURL(tt.url, dialTestConn(tt.r, &buf), redis.DialUseTLS(true))
655-
if err != nil {
656-
t.Errorf("%s dial error: %v", tt.description, err)
657-
continue
658-
}
659-
if w := buf.String(); w != tt.w {
660-
t.Errorf("%s commands = %q, want %q", tt.description, w, tt.w)
661-
}
659+
t.Run(tt.description, func(t *testing.T) {
660+
var buf bytes.Buffer
661+
// UseTLS should be ignored in all of these tests.
662+
_, err := redis.DialURL(tt.url, dialTestConn(tt.r, &buf), redis.DialUseTLS(true))
663+
if err != nil {
664+
t.Errorf("%s dial error: %v, buf: %v", tt.description, err, buf.String())
665+
return
666+
}
667+
if w := buf.String(); w != tt.w {
668+
t.Errorf("%s commands = %q, want %q", tt.description, w, tt.w)
669+
}
670+
})
662671
}
663672
}
664673

0 commit comments

Comments
 (0)