gitee.com/h79/goutils@v1.22.10/common/server/address.go (about)

     1  package server
     2  
     3  import (
     4  	"fmt"
     5  	"gitee.com/h79/goutils/common/random"
     6  	"gitee.com/h79/goutils/common/stringutil"
     7  	"gitee.com/h79/goutils/common/system"
     8  	"net"
     9  	"net/url"
    10  	"regexp"
    11  	"sort"
    12  	"strings"
    13  )
    14  
    15  type Address struct {
    16  	Scheme  string `json:"scheme" yaml:"scheme" xml:"scheme"`
    17  	Host    string `json:"host" yaml:"host" xml:"host"`
    18  	Port    int    `json:"port" yaml:"port" xml:"port"`
    19  	Path    string `json:"path,omitempty" yaml:"path,omitempty" xml:"path,omitempty"`
    20  	Name    string `json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"`
    21  	Weight  int    `json:"weight,omitempty" yaml:"weight,omitempty" xml:"weight,omitempty"`
    22  	Timeout int    `json:"timeout,omitempty" yaml:"timeout,omitempty" xml:"timeout,omitempty"`
    23  }
    24  
    25  func (s Address) IsHttp() bool {
    26  	return s.Scheme == "http" || s.Scheme == "https"
    27  }
    28  
    29  func (s Address) IsWs() bool {
    30  	return s.Scheme == "ws" || s.Scheme == "wss"
    31  }
    32  
    33  func (s Address) IsScheme(scheme string) bool {
    34  	return s.Scheme == scheme
    35  }
    36  
    37  // To
    38  // scheme://host:port
    39  func (s Address) To() string {
    40  	var buf strings.Builder
    41  	if len(s.Scheme) > 0 {
    42  		buf.WriteString(s.Scheme)
    43  		buf.WriteString("://")
    44  	}
    45  	if len(s.Host) > 0 {
    46  		buf.WriteString(s.Host)
    47  	}
    48  	if s.Port > 0 {
    49  		buf.WriteByte(':')
    50  		buf.WriteString(stringutil.IntToString(s.Port))
    51  	}
    52  	if len(s.Path) > 0 {
    53  		if s.Path[0] != '/' {
    54  			buf.WriteByte('/')
    55  		}
    56  		buf.WriteString(s.Path)
    57  	}
    58  	return buf.String()
    59  }
    60  
    61  // Adjust 如果IP是自己,调整为 127.0.0.1
    62  func (s Address) Adjust() Address {
    63  	if !s.HasIP() {
    64  		return s
    65  	}
    66  	s.Host = system.IPIsSelf(s.Host)
    67  	return s
    68  }
    69  
    70  func (s Address) HasScheme() bool {
    71  	return s.Scheme != ""
    72  }
    73  
    74  func (s Address) HasPort() bool {
    75  	return s.Port > 0
    76  }
    77  
    78  func (s Address) HasIP() bool {
    79  	return net.ParseIP(s.Host) != nil
    80  }
    81  
    82  var reg = regexp.MustCompile(".com|.cn|.net|.org")
    83  
    84  // HasDomain 简单的域名 .com,.cn
    85  func (s Address) HasDomain() bool {
    86  	return reg.MatchString(s.Host)
    87  }
    88  
    89  func (s Address) SetHost(host string) {
    90  	s.Host = host
    91  }
    92  
    93  func (s Address) IsEqual(addr Address) bool {
    94  	return addr.Host == s.Host && addr.Port == s.Port
    95  }
    96  
    97  // IsSelf 服务就是自己
    98  func (s Address) IsSelf(addr string) bool {
    99  	self, er := Parse(addr)
   100  	if er != nil {
   101  		return false
   102  	}
   103  	return self.Adjust().IsEqual(s.Clone().Adjust())
   104  }
   105  
   106  func (s Address) IsValid() bool {
   107  	return len(s.Host) > 0
   108  }
   109  
   110  func (s Address) Clone() Address {
   111  	return Address{
   112  		Scheme: s.Scheme,
   113  		Host:   s.Host,
   114  		Port:   s.Port,
   115  		Path:   s.Path,
   116  		Name:   s.Name,
   117  	}
   118  }
   119  
   120  type Addresses []Address
   121  
   122  // Add @param s = host:port
   123  func (ay *Addresses) Add(addr string) {
   124  	ser, err := Parse(addr)
   125  	if err != nil {
   126  		return
   127  	}
   128  	*ay = append(*ay, ser)
   129  }
   130  
   131  func (ay Addresses) Array() []string {
   132  
   133  	var points []string
   134  	for i := range ay {
   135  		points = append(points, ay[i].To())
   136  	}
   137  	return points
   138  }
   139  
   140  func (ay Addresses) ToWeight() {
   141  	r := random.Random()
   142  	for index := range ay {
   143  		ay[index].Weight = r.Intn(1000)
   144  	}
   145  	sort.Sort(ay)
   146  }
   147  
   148  func (ay Addresses) Len() int {
   149  	return len(ay)
   150  }
   151  
   152  func (ay Addresses) Swap(i, j int) {
   153  	temp := ay[i]
   154  	ay[i] = ay[j]
   155  	ay[j] = temp
   156  }
   157  
   158  // Less 权重越大,在前面
   159  func (ay Addresses) Less(i, j int) bool {
   160  	return ay[i].Weight >= ay[j].Weight
   161  }
   162  
   163  func ParseV2(addr net.Addr, pubIp string) Address {
   164  	host := addr.(*net.TCPAddr).IP.String()
   165  	port := addr.(*net.TCPAddr).Port
   166  	if host == "" || host == "::" || host == ":::" {
   167  		p := strings.SplitN(pubIp, ":", 2)
   168  		host = p[0]
   169  	}
   170  	return Address{Host: host, Port: port}
   171  }
   172  
   173  func Parse(addr string) (Address, error) {
   174  	u, err := url.Parse(addr)
   175  	if err != nil {
   176  		host := strings.Split(addr, ":")
   177  		if len(host) < 2 {
   178  			return Address{}, err
   179  		}
   180  		if net.ParseIP(host[0]) == nil {
   181  			return Address{}, fmt.Errorf("addr='%v' is not ip", addr)
   182  		}
   183  		return Address{
   184  			Host: host[0],
   185  			Port: stringutil.StringToInt(host[1]),
   186  		}, nil
   187  	}
   188  	return Address{
   189  		Scheme: u.Scheme,
   190  		Host:   u.Hostname(),
   191  		Port:   stringutil.StringToInt(u.Port()),
   192  		Path:   u.Path,
   193  	}, nil
   194  }
   195  
   196  // ParseWithSeparate
   197  // info = name|scheme://host:post|timeout|weight
   198  func ParseWithSeparate(info string) Address {
   199  	var name string
   200  	var timeout int
   201  	var weight int
   202  	s := strings.Split(info, "|")
   203  	l := len(s)
   204  	if l >= 2 {
   205  		name = s[0]
   206  		info = s[1]
   207  
   208  		if l >= 3 {
   209  			timeout = stringutil.StringToInt(s[2])
   210  		}
   211  
   212  		if l >= 4 {
   213  			weight = stringutil.StringToInt(s[3])
   214  		}
   215  	}
   216  	addr, er := Parse(info)
   217  	if er != nil {
   218  		panic(er)
   219  	}
   220  	addr.Weight = weight
   221  	addr.Timeout = timeout
   222  	addr.Name = name
   223  	return addr
   224  }