You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

redis.go 2.8KB

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