diff --git a/changelog.md b/changelog.md index c902401..a89be70 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +v0.2.0 +====== + +* Fix parsing connection address with non-ip host and without `tcp://` scheme, like `localhost:3301` - previously connecting with such an address resulted in configuration error + v0.1.1 ====== diff --git a/connection.go b/connection.go index a62b905..0d08378 100644 --- a/connection.go +++ b/connection.go @@ -5,11 +5,13 @@ import ( "bytes" "context" "errors" + "fmt" "io" "net" "net/url" "runtime" "strconv" + "strings" "sync" "sync/atomic" "time" @@ -400,15 +402,18 @@ func (conn *Connection) timeouts() { } func optsFromAddr(addr string, opts Opts) (Opts, error) { - u, err := url.Parse(addr) - if err != nil { - if _, _, err := net.SplitHostPort(addr); err == nil { + if !strings.HasPrefix(addr, "tcp://") && !strings.HasPrefix(addr, "unix://") { + if host, port, err := net.SplitHostPort(addr); err == nil && host != "" && port != "" { opts.network = "tcp" opts.address = addr return opts, nil } return opts, errors.New("malformed connection address") } + u, err := url.Parse(addr) + if err != nil { + return opts, fmt.Errorf("malformed connection address URL: %w", err) + } switch u.Scheme { case "tcp": opts.network = "tcp" diff --git a/connection_test.go b/connection_test.go new file mode 100644 index 0000000..27af592 --- /dev/null +++ b/connection_test.go @@ -0,0 +1,70 @@ +package tarantool + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestRedisShard_OptsFromAddr(t *testing.T) { + opts, err := optsFromAddr("127.0.0.1:3301", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "127.0.0.1:3301", opts.address) + + opts, err = optsFromAddr("localhost:3301", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "localhost:3301", opts.address) + + _, err = optsFromAddr("localhost:", Opts{}) + require.Error(t, err) + + opts, err = optsFromAddr("tcp://localhost:3301", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "localhost:3301", opts.address) + + opts, err = optsFromAddr("tcp://user:pass@localhost:3301", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "localhost:3301", opts.address) + require.Equal(t, "user", opts.User) + require.Equal(t, "pass", opts.Password) + + opts, err = optsFromAddr("tcp://localhost:3301/rest", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "localhost:3301", opts.address) + require.Equal(t, "", opts.Password) + + opts, err = optsFromAddr("unix://user:pass@/var/run/tarantool/my_instance.sock", Opts{}) + require.NoError(t, err) + require.Equal(t, "unix", opts.network) + require.Equal(t, "/var/run/tarantool/my_instance.sock", opts.address) + require.Equal(t, "pass", opts.Password) + require.Equal(t, "user", opts.User) + + opts, err = optsFromAddr("tcp://[fe80::1]:3301", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "[fe80::1]:3301", opts.address) + + opts, err = optsFromAddr("redis://127.0.0.1:3301", Opts{}) + require.Error(t, err) + + opts, err = optsFromAddr("tcp://:pass@localhost:3301?connect_timeout=2s&read_timeout=3s&write_timeout=4s&request_timeout=5s&reconnect_delay=6s&max_reconnects=7&skip_schema=true", Opts{}) + require.NoError(t, err) + require.Equal(t, "tcp", opts.network) + require.Equal(t, "localhost:3301", opts.address) + require.Equal(t, "pass", opts.Password) + require.Equal(t, "", opts.User) + require.Equal(t, 2*time.Second, opts.ConnectTimeout) + require.Equal(t, 3*time.Second, opts.ReadTimeout) + require.Equal(t, 4*time.Second, opts.WriteTimeout) + require.Equal(t, 5*time.Second, opts.RequestTimeout) + require.Equal(t, 6*time.Second, opts.ReconnectDelay) + require.Equal(t, uint64(7), opts.MaxReconnects) + require.True(t, opts.SkipSchema) +}