@@ -19,7 +19,6 @@ import (
1919 "encoding/base64"
2020 "fmt"
2121 "io"
22- "net/url"
2322 "strconv"
2423 "strings"
2524 "time"
@@ -513,159 +512,3 @@ func escape(s string) string {
513512 )
514513 return r .Replace (s )
515514}
516-
517- func ParseRedisClusterURL (redisURL string ) (* redis.ClusterOptions , error ) {
518- options := & redis.ClusterOptions {}
519- uri := redisURL
520-
521- var err error
522- if strings .HasPrefix (redisURL , storage .RedisClusterPrefix ) {
523- uri = uri [len (storage .RedisClusterPrefix ):]
524- } else {
525- return nil , fmt .Errorf ("scheme must be \" redis+cluster\" " )
526- }
527-
528- if idx := strings .Index (uri , "@" ); idx != - 1 {
529- userInfo := uri [:idx ]
530- uri = uri [idx + 1 :]
531-
532- username := userInfo
533- var password string
534-
535- if idx := strings .Index (userInfo , ":" ); idx != - 1 {
536- username = userInfo [:idx ]
537- password = userInfo [idx + 1 :]
538- }
539-
540- // Validate and process the username.
541- if strings .Contains (username , "/" ) {
542- return nil , fmt .Errorf ("unescaped slash in username" )
543- }
544- options .Username , err = url .PathUnescape (username )
545- if err != nil {
546- return nil , errors .Wrap (err , fmt .Errorf ("invalid username" ))
547- }
548-
549- // Validate and process the password.
550- if strings .Contains (password , ":" ) {
551- return nil , fmt .Errorf ("unescaped colon in password" )
552- }
553- if strings .Contains (password , "/" ) {
554- return nil , fmt .Errorf ("unescaped slash in password" )
555- }
556- options .Password , err = url .PathUnescape (password )
557- if err != nil {
558- return nil , errors .Wrap (err , fmt .Errorf ("invalid password" ))
559- }
560- }
561-
562- // fetch the hosts field
563- hosts := uri
564- if idx := strings .IndexAny (uri , "/?@" ); idx != - 1 {
565- if uri [idx ] == '@' {
566- return nil , fmt .Errorf ("unescaped @ sign in user info" )
567- }
568- hosts = uri [:idx ]
569- }
570-
571- options .Addrs = strings .Split (hosts , "," )
572- uri = uri [len (hosts ):]
573- if len (uri ) > 0 && uri [0 ] == '/' {
574- uri = uri [1 :]
575- }
576-
577- // grab connection arguments from URI
578- connectionArgsFromQueryString , err := extractQueryArgsFromURI (uri )
579- if err != nil {
580- return nil , err
581- }
582- for _ , pair := range connectionArgsFromQueryString {
583- err = addOption (options , pair )
584- if err != nil {
585- return nil , err
586- }
587- }
588-
589- return options , nil
590- }
591-
592- func extractQueryArgsFromURI (uri string ) ([]string , error ) {
593- if len (uri ) == 0 {
594- return nil , nil
595- }
596-
597- if uri [0 ] != '?' {
598- return nil , errors .New ("must have a ? separator between path and query" )
599- }
600-
601- uri = uri [1 :]
602- if len (uri ) == 0 {
603- return nil , nil
604- }
605- return strings .FieldsFunc (uri , func (r rune ) bool { return r == ';' || r == '&' }), nil
606- }
607-
608- type optionHandler struct {
609- int * int
610- bool * bool
611- duration * time.Duration
612- }
613-
614- func addOption (options * redis.ClusterOptions , pair string ) error {
615- kv := strings .SplitN (pair , "=" , 2 )
616- if len (kv ) != 2 || kv [0 ] == "" {
617- return fmt .Errorf ("invalid option" )
618- }
619-
620- key , err := url .QueryUnescape (kv [0 ])
621- if err != nil {
622- return errors .Wrap (err , errors .Errorf ("invalid option key %q" , kv [0 ]))
623- }
624-
625- value , err := url .QueryUnescape (kv [1 ])
626- if err != nil {
627- return errors .Wrap (err , errors .Errorf ("invalid option value %q" , kv [1 ]))
628- }
629-
630- handlers := map [string ]optionHandler {
631- "max_retries" : {int : & options .MaxRetries },
632- "min_retry_backoff" : {duration : & options .MinRetryBackoff },
633- "max_retry_backoff" : {duration : & options .MaxRetryBackoff },
634- "dial_timeout" : {duration : & options .DialTimeout },
635- "read_timeout" : {duration : & options .ReadTimeout },
636- "write_timeout" : {duration : & options .WriteTimeout },
637- "pool_fifo" : {bool : & options .PoolFIFO },
638- "pool_size" : {int : & options .PoolSize },
639- "pool_timeout" : {duration : & options .PoolTimeout },
640- "min_idle_conns" : {int : & options .MinIdleConns },
641- "max_idle_conns" : {int : & options .MaxIdleConns },
642- "conn_max_idle_time" : {duration : & options .ConnMaxIdleTime },
643- "conn_max_lifetime" : {duration : & options .ConnMaxLifetime },
644- }
645-
646- lowerKey := strings .ToLower (key )
647- if handler , ok := handlers [lowerKey ]; ok {
648- if handler .int != nil {
649- * handler .int , err = strconv .Atoi (value )
650- if err != nil {
651- return errors .Wrap (err , fmt .Errorf ("invalid '%s' value: %q" , key , value ))
652- }
653- } else if handler .duration != nil {
654- * handler .duration , err = time .ParseDuration (value )
655- if err != nil {
656- return errors .Wrap (err , fmt .Errorf ("invalid '%s' value: %q" , key , value ))
657- }
658- } else if handler .bool != nil {
659- * handler .bool , err = strconv .ParseBool (value )
660- if err != nil {
661- return errors .Wrap (err , fmt .Errorf ("invalid '%s' value: %q" , key , value ))
662- }
663- } else {
664- return fmt .Errorf ("redis: unexpected option: %s" , key )
665- }
666- } else {
667- return fmt .Errorf ("redis: unexpected option: %s" , key )
668- }
669-
670- return nil
671- }
0 commit comments