github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/nosql/redis.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 package nosql 7 8 import ( 9 "net/url" 10 "strconv" 11 "strings" 12 ) 13 14 // The file contains common redis connection functions 15 16 // ToRedisURI converts old style connections to a RedisURI 17 // 18 // A RedisURI matches the pattern: 19 // 20 // redis://[username:password@]host[:port][/database][?[option=value]*] 21 // rediss://[username:password@]host[:port][/database][?[option=value]*] 22 // redis+socket://[username:password@]path[/database][?[option=value]*] 23 // redis+sentinel://[password@]host1 [: port1][, host2 [:port2]][, hostN [:portN]][/ database][?[option=value]*] 24 // redis+cluster://[password@]host1 [: port1][, host2 [:port2]][, hostN [:portN]][/ database][?[option=value]*] 25 // 26 // We have previously used a URI like: 27 // addrs=127.0.0.1:6379 db=0 28 // network=tcp,addr=127.0.0.1:6379,password=macaron,db=0,pool_size=100,idle_timeout=180 29 // 30 // We need to convert this old style to the new style 31 func ToRedisURI(connection string) *url.URL { 32 uri, err := url.Parse(connection) 33 if err == nil && strings.HasPrefix(uri.Scheme, "redis") { 34 // OK we're going to assume that this is a reasonable redis URI 35 return uri 36 } 37 38 // Let's set a nice default 39 uri, _ = url.Parse("redis://127.0.0.1:6379/0") 40 network := "tcp" 41 query := uri.Query() 42 43 // OK so there are two types: Space delimited and Comma delimited 44 // Let's assume that we have a space delimited string - as this is the most common 45 fields := strings.Fields(connection) 46 if len(fields) == 1 { 47 // It's a comma delimited string, then... 48 fields = strings.Split(connection, ",") 49 } 50 for _, f := range fields { 51 items := strings.SplitN(f, "=", 2) 52 if len(items) < 2 { 53 continue 54 } 55 switch strings.ToLower(items[0]) { 56 case "network": 57 if items[1] == "unix" { 58 uri.Scheme = "redis+socket" 59 } 60 network = items[1] 61 case "addrs": 62 uri.Host = items[1] 63 // now we need to handle the clustering 64 if strings.Contains(items[1], ",") && network == "tcp" { 65 uri.Scheme = "redis+cluster" 66 } 67 case "addr": 68 uri.Host = items[1] 69 case "password": 70 uri.User = url.UserPassword(uri.User.Username(), items[1]) 71 case "username": 72 password, set := uri.User.Password() 73 if !set { 74 uri.User = url.User(items[1]) 75 } else { 76 uri.User = url.UserPassword(items[1], password) 77 } 78 case "db": 79 uri.Path = "/" + items[1] 80 case "idle_timeout": 81 _, err := strconv.Atoi(items[1]) 82 if err == nil { 83 query.Add("idle_timeout", items[1]+"s") 84 } else { 85 query.Add("idle_timeout", items[1]) 86 } 87 default: 88 // Other options become query params 89 query.Add(items[0], items[1]) 90 } 91 } 92 93 // Finally we need to fix up the Host if we have a unix port 94 if uri.Scheme == "redis+socket" { 95 query.Set("db", uri.Path) 96 uri.Path = uri.Host 97 uri.Host = "" 98 } 99 uri.RawQuery = query.Encode() 100 101 return uri 102 }