Skip to content
Snippets Groups Projects
config_url.go 4.87 KiB
Newer Older
vito.he's avatar
vito.he committed
package config
fangyincheng's avatar
fangyincheng committed

import (
fangyincheng's avatar
fangyincheng committed
	"fmt"
	"net"
	"net/url"
	"strconv"
	"strings"
	"time"
)

import (
	jerrors "github.com/juju/errors"
)

/////////////////////////////////
// dubbo role type
/////////////////////////////////

const (
	CONSUMER = iota
	CONFIGURATOR
	ROUTER
	PROVIDER
)

var (
	DubboNodes = [...]string{"consumers", "configurators", "routers", "providers"}
	DubboRole  = [...]string{"consumer", "", "", "provider"}
)

type RoleType int

func (t RoleType) String() string {
	return DubboNodes[t]
}

func (t RoleType) Role() string {
	return DubboRole[t]
vito.he's avatar
vito.he committed
type baseUrl struct {
vito.he's avatar
vito.he committed
	Protocol     string `required:"true"  yaml:"protocol"  json:"protocol,omitempty"`
	Location     string // ip+port
	Ip           string
	Port         string
	Timeout      time.Duration
	Params       url.Values
vito.he's avatar
vito.he committed
	PrimitiveURL string
	ctx          context.Context
type URL struct {
vito.he's avatar
vito.he committed
	baseUrl
	Service string
	Path     string `yaml:"path" json:"path,omitempty"` // like  /com.ikurento.dubbo.UserProvider3
	Username string
	Password string
type option func(*URL)

func WithUsername(username string) option {
	return func(url *URL) {
		url.Username = username
	}
}

func WithPassword(pwd string) option {
	return func(url *URL) {
		url.Password = pwd
	}
}
func WithParams(params url.Values) option {
	return func(url *URL) {
		url.Params = params
	}
}

vito.he's avatar
vito.he committed
func WithProtocol(proto string) option {
	return func(url *URL) {
		url.Protocol = proto
	}
}
func WithIp(ip string) option {
	return func(url *URL) {
		url.Ip = ip
	}
}

func WithPort(port string) option {
	return func(url *URL) {
		url.Port = port
	}
}

func WithPath(path string) option {
	return func(url *URL) {
		url.Path = path
	}
}

func NewURLWithOptions(service string, opts ...option) *URL {
	url := &URL{
		Service: service,
	}
	for _, opt := range opts {
		opt(url)
	}
	return url
}

func NewURL(ctx context.Context, urlString string, opts ...option) (*URL, error) {
fangyincheng's avatar
fangyincheng committed
	var (
		err          error
		rawUrlString string
		serviceUrl   *url.URL
fangyincheng's avatar
fangyincheng committed
		s            = &URL{baseUrl: baseUrl{ctx: ctx}}
	// new a null instance
	if urlString == "" {
		return s, nil
	}

fangyincheng's avatar
fangyincheng committed
	rawUrlString, err = url.QueryUnescape(urlString)
	if err != nil {
		return nil, jerrors.Errorf("url.QueryUnescape(%s),  error{%v}", urlString, err)
	}

	serviceUrl, err = url.Parse(rawUrlString)
	if err != nil {
		return nil, jerrors.Errorf("url.Parse(url string{%s}),  error{%v}", rawUrlString, err)
	}

	s.Params, err = url.ParseQuery(serviceUrl.RawQuery)
fangyincheng's avatar
fangyincheng committed
	if err != nil {
		return nil, jerrors.Errorf("url.ParseQuery(raw url string{%s}),  error{%v}", serviceUrl.RawQuery, err)
	}

vito.he's avatar
vito.he committed
	s.PrimitiveURL = urlString
	s.Protocol = serviceUrl.Scheme
	s.Username = serviceUrl.User.Username()
	s.Password, _ = serviceUrl.User.Password()
vito.he's avatar
vito.he committed
	s.Location = serviceUrl.Host
	s.Path = serviceUrl.Path
	if strings.Contains(s.Location, ":") {
		s.Ip, s.Port, err = net.SplitHostPort(s.Location)
fangyincheng's avatar
fangyincheng committed
		if err != nil {
vito.he's avatar
vito.he committed
			return nil, jerrors.Errorf("net.SplitHostPort(Url.Host{%s}), error{%v}", s.Location, err)
	timeoutStr := s.Params.Get("timeout")
fangyincheng's avatar
fangyincheng committed
	if len(timeoutStr) == 0 {
		timeoutStr = s.Params.Get("default.timeout")
fangyincheng's avatar
fangyincheng committed
	}
	if len(timeoutStr) != 0 {
		timeout, err := strconv.Atoi(timeoutStr)
		if err == nil && timeout != 0 {
vito.he's avatar
vito.he committed
			s.Timeout = time.Duration(timeout * 1e6) // timeout unit is millisecond
fangyincheng's avatar
fangyincheng committed
	return s, nil
}

func (c *URL) Key() string {
	return fmt.Sprintf(
		"%s://%s:%s@%s:%s/%s",
		c.Protocol, c.Username, c.Password, c.Ip, c.Port, c.Path)
vito.he's avatar
vito.he committed
}

func (c *URL) URLEqual(url URL) bool {
vito.he's avatar
vito.he committed
	if c.Key() != url.Key() {
		return false
	}
	return true
}
//func (c URL) String() string {
//	return fmt.Sprintf(
//		"DefaultServiceURL{Protocol:%s, Location:%s, Path:%s, Ip:%s, Port:%s, "+
//			"Timeout:%s, Version:%s, Group:%s,  Params:%+v}",
//		c.Protocol, c.Location, c.Path, c.Ip, c.Port,
//		c.Timeout, c.Version, c.Group, c.Params)
//}

func (c *URL) String() string {
	buildString := fmt.Sprintf(
		"%s://%s:%s@%s:%s/%s?",
		c.Protocol, c.Username, c.Password, c.Ip, c.Port, c.Path)
	for k, v := range c.Params {
		buildString += "&" + k + "=" + v[0]
	}
	return buildString
}

func (c *URL) Context() context.Context {
	return c.ctx
}

func (c *URL) GetParam(s string, d string) string {
	var r string
	if r = c.Params.Get(s); r == "" {
		r = d
	}
	return r
}

func (c *URL) GetParamInt(s string, d int64) int64 {
	var r int
	var err error
	if r, err = strconv.Atoi(c.Params.Get(s)); r == 0 || err != nil {
		return d
	}
	return int64(r)
}

func (c *URL) GetMethodParamInt(method string, key string, d int64) int64 {
	var r int
	var err error
	if r, err = strconv.Atoi(c.Params.Get("methods." + method + "." + key)); r == 0 || err != nil {
		return d
	}
	return int64(r)
}

func (c *URL) GetMethodParam(method string, key string, d string) string {
	var r string
	if r = c.Params.Get(c.Params.Get("methods." + method + "." + key)); r == "" {
		r = d
	}
	return r
}