Skip to content

Commit

Permalink
fix: DialURL compatibility with redis-cli (#566)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
stevenh committed Jun 10, 2021
1 parent 72af812 commit 46992b0
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
13 changes: 12 additions & 1 deletion redis/conn.go
Expand Up @@ -168,6 +168,7 @@ func DialPassword(password string) DialOption {

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

if u.User != nil {
password, isSet := u.User.Password()
username := u.User.Username()
if isSet {
options = append(options, DialUsername(u.User.Username()), DialPassword(password))
if username != "" {
// ACL
options = append(options, DialUsername(username), DialPassword(password))
} else {
// requirepass - user-info username:password with blank username
options = append(options, DialPassword(password))
}
} else if username != "" {
// requirepass - redis-cli compatibility which treats as single arg in user-info as a password
options = append(options, DialPassword(username))
}
}

Expand Down
29 changes: 19 additions & 10 deletions redis/conn_test.go
Expand Up @@ -640,6 +640,13 @@ var dialURLTests = []struct {
w string
}{
{"password", "redis://:abc123@localhost", "+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
{"password redis-cli compat", "redis://abc123@localhost", "+OK\r\n", "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"username", "redis://x:@localhost", "+OK\r\n", ""},
{"database 3", "redis://localhost/3", "+OK\r\n", "*2\r\n$6\r\nSELECT\r\n$1\r\n3\r\n"},
Expand All @@ -649,16 +656,18 @@ var dialURLTests = []struct {

func TestDialURL(t *testing.T) {
for _, tt := range dialURLTests {
var buf bytes.Buffer
// UseTLS should be ignored in all of these tests.
_, err := redis.DialURL(tt.url, dialTestConn(tt.r, &buf), redis.DialUseTLS(true))
if err != nil {
t.Errorf("%s dial error: %v", tt.description, err)
continue
}
if w := buf.String(); w != tt.w {
t.Errorf("%s commands = %q, want %q", tt.description, w, tt.w)
}
t.Run(tt.description, func(t *testing.T) {
var buf bytes.Buffer
// UseTLS should be ignored in all of these tests.
_, err := redis.DialURL(tt.url, dialTestConn(tt.r, &buf), redis.DialUseTLS(true))
if err != nil {
t.Errorf("%s dial error: %v, buf: %v", tt.description, err, buf.String())
return
}
if w := buf.String(); w != tt.w {
t.Errorf("%s commands = %q, want %q", tt.description, w, tt.w)
}
})
}
}

Expand Down

0 comments on commit 46992b0

Please sign in to comment.