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