123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- // Copyright 2020 The Gitea Authors. All rights reserved.
- // SPDX-License-Identifier: MIT
-
- package nosql
-
- import (
- "net/url"
- "strconv"
- "strings"
- )
-
- // The file contains common redis connection functions
-
- // ToRedisURI converts old style connections to a RedisURI
- //
- // A RedisURI matches the pattern:
- //
- // redis://[username:password@]host[:port][/database][?[option=value]*]
- // rediss://[username:password@]host[:port][/database][?[option=value]*]
- // redis+socket://[username:password@]path[/database][?[option=value]*]
- // redis+sentinel://[password@]host1 [: port1][, host2 [:port2]][, hostN [:portN]][/ database][?[option=value]*]
- // redis+cluster://[password@]host1 [: port1][, host2 [:port2]][, hostN [:portN]][/ database][?[option=value]*]
- //
- // We have previously used a URI like:
- // addrs=127.0.0.1:6379 db=0
- // network=tcp,addr=127.0.0.1:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
- //
- // We need to convert this old style to the new style
- func ToRedisURI(connection string) *url.URL {
- uri, err := url.Parse(connection)
- if err == nil && strings.HasPrefix(uri.Scheme, "redis") {
- // OK we're going to assume that this is a reasonable redis URI
- return uri
- }
-
- // Let's set a nice default
- uri, _ = url.Parse("redis://127.0.0.1:6379/0")
- network := "tcp"
- query := uri.Query()
-
- // OK so there are two types: Space delimited and Comma delimited
- // Let's assume that we have a space delimited string - as this is the most common
- fields := strings.Fields(connection)
- if len(fields) == 1 {
- // It's a comma delimited string, then...
- fields = strings.Split(connection, ",")
- }
- for _, f := range fields {
- items := strings.SplitN(f, "=", 2)
- if len(items) < 2 {
- continue
- }
- switch strings.ToLower(items[0]) {
- case "network":
- if items[1] == "unix" {
- uri.Scheme = "redis+socket"
- }
- network = items[1]
- case "addrs":
- uri.Host = items[1]
- // now we need to handle the clustering
- if strings.Contains(items[1], ",") && network == "tcp" {
- uri.Scheme = "redis+cluster"
- }
- case "addr":
- uri.Host = items[1]
- case "password":
- uri.User = url.UserPassword(uri.User.Username(), items[1])
- case "username":
- password, set := uri.User.Password()
- if !set {
- uri.User = url.User(items[1])
- } else {
- uri.User = url.UserPassword(items[1], password)
- }
- case "db":
- uri.Path = "/" + items[1]
- case "idle_timeout":
- _, err := strconv.Atoi(items[1])
- if err == nil {
- query.Add("idle_timeout", items[1]+"s")
- } else {
- query.Add("idle_timeout", items[1])
- }
- default:
- // Other options become query params
- query.Add(items[0], items[1])
- }
- }
-
- // Finally we need to fix up the Host if we have a unix port
- if uri.Scheme == "redis+socket" {
- query.Set("db", uri.Path)
- uri.Path = uri.Host
- uri.Host = ""
- }
- uri.RawQuery = query.Encode()
-
- return uri
- }
|