2020-09-28 00:09:46 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2020-09-28 00:09:46 +03:00
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
}