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 }