Skip to content

Commit d31cf6c

Browse files
authored
Add unix socket connection by url stirng. (#1511)
* add unix connectin by url string
1 parent 3e42145 commit d31cf6c

File tree

2 files changed

+81
-10
lines changed

2 files changed

+81
-10
lines changed

options.go

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Limiter interface {
2929
ReportResult(result error)
3030
}
3131

32+
// Options keeps the settings to setup redis connection.
3233
type Options struct {
3334
// The network type, either tcp or unix.
3435
// Default is tcp.
@@ -187,23 +188,32 @@ func (opt *Options) clone() *Options {
187188
}
188189

189190
// ParseURL parses an URL into Options that can be used to connect to Redis.
191+
// Scheme is required.
192+
// There are two connection types: by tcp socket and by unix socket.
193+
// Tcp connection:
194+
// redis://<user>:<password>@<host>:<port>/<db_number>
195+
// Unix connection:
196+
// unix://<user>:<password>@</path/to/redis.sock>?db=<db_number>
190197
func ParseURL(redisURL string) (*Options, error) {
191-
o := &Options{Network: "tcp"}
192198
u, err := url.Parse(redisURL)
193199
if err != nil {
194200
return nil, err
195201
}
196202

197-
if u.Scheme != "redis" && u.Scheme != "rediss" {
198-
return nil, errors.New("invalid redis URL scheme: " + u.Scheme)
203+
switch u.Scheme {
204+
case "redis", "rediss":
205+
return setupTCPConn(u)
206+
case "unix":
207+
return setupUnixConn(u)
208+
default:
209+
return nil, fmt.Errorf("invalid redis URL scheme: %s", u.Scheme)
199210
}
211+
}
200212

201-
if u.User != nil {
202-
o.Username = u.User.Username()
203-
if p, ok := u.User.Password(); ok {
204-
o.Password = p
205-
}
206-
}
213+
func setupTCPConn(u *url.URL) (*Options, error) {
214+
o := &Options{Network: "tcp"}
215+
216+
o.Username, o.Password = getUserPassword(u)
207217

208218
if len(u.Query()) > 0 {
209219
return nil, errors.New("no options supported")
@@ -232,15 +242,52 @@ func ParseURL(redisURL string) (*Options, error) {
232242
return nil, fmt.Errorf("invalid redis database number: %q", f[0])
233243
}
234244
default:
235-
return nil, errors.New("invalid redis URL path: " + u.Path)
245+
return nil, fmt.Errorf("invalid redis URL path: %s", u.Path)
236246
}
237247

238248
if u.Scheme == "rediss" {
239249
o.TLSConfig = &tls.Config{ServerName: h}
240250
}
251+
252+
return o, nil
253+
}
254+
255+
func setupUnixConn(u *url.URL) (*Options, error) {
256+
o := &Options{
257+
Network: "unix",
258+
}
259+
260+
if strings.TrimSpace(u.Path) == "" { // path is required with unix connection
261+
return nil, errors.New("empty redis unix socket path")
262+
}
263+
o.Addr = u.Path
264+
265+
o.Username, o.Password = getUserPassword(u)
266+
267+
dbStr := u.Query().Get("db")
268+
if dbStr == "" {
269+
return o, nil // if database is not set, connect to 0 db.
270+
}
271+
db, err := strconv.Atoi(dbStr)
272+
if err != nil {
273+
return nil, fmt.Errorf("invalid reids database number: %s", err)
274+
}
275+
o.DB = db
276+
241277
return o, nil
242278
}
243279

280+
func getUserPassword(u *url.URL) (string, string) {
281+
var user, password string
282+
if u.User != nil {
283+
user = u.User.Username()
284+
if p, ok := u.User.Password(); ok {
285+
password = p
286+
}
287+
}
288+
return user, password
289+
}
290+
244291
func newConnPool(opt *Options) *pool.ConnPool {
245292
return pool.NewConnPool(&pool.Options{
246293
Dialer: func(ctx context.Context) (net.Conn, error) {

options_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,30 @@ func TestParseURL(t *testing.T) {
6666
0, false, nil,
6767
"foo", "bar",
6868
},
69+
{
70+
"unix:///tmp/redis.sock",
71+
"/tmp/redis.sock",
72+
0, false, nil,
73+
"", "",
74+
},
75+
{
76+
"unix://foo:bar@/tmp/redis.sock",
77+
"/tmp/redis.sock",
78+
0, false, nil,
79+
"foo", "bar",
80+
},
81+
{
82+
"unix://foo:bar@/tmp/redis.sock?db=3",
83+
"/tmp/redis.sock",
84+
3, false, nil,
85+
"foo", "bar",
86+
},
87+
{
88+
"unix://foo:bar@/tmp/redis.sock?db=test",
89+
"/tmp/redis.sock",
90+
0, false, errors.New("invalid reids database number: strconv.Atoi: parsing \"test\": invalid syntax"),
91+
"", "",
92+
},
6993
{
7094
"redis://localhost/?abc=123",
7195
"",

0 commit comments

Comments
 (0)