github.com/qiniu/go-sdk/v7@v7.27.0/storage/region.go (about) 1 package storage 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 "sync" 8 9 "github.com/qiniu/go-sdk/v7/auth" 10 "github.com/qiniu/go-sdk/v7/internal/clientv2" 11 "github.com/qiniu/go-sdk/v7/storagev2/apis" 12 "github.com/qiniu/go-sdk/v7/storagev2/defaults" 13 "github.com/qiniu/go-sdk/v7/storagev2/http_client" 14 region_v2 "github.com/qiniu/go-sdk/v7/storagev2/region" 15 ) 16 17 // 存储所在的地区,例如华东,华南,华北 18 // 每个存储区域可能有多个机房信息,每个机房可能有多个上传入口 19 type Region struct { 20 // 上传入口 21 SrcUpHosts []string `json:"src_up,omitempty"` 22 23 // 加速上传入口 24 CdnUpHosts []string `json:"cdn_up,omitempty"` 25 26 // 获取文件信息入口 27 RsHost string `json:"rs,omitempty"` 28 29 // bucket列举入口 30 RsfHost string `json:"rsf,omitempty"` 31 32 ApiHost string `json:"api,omitempty"` 33 34 // 存储io 入口 35 IovipHost string `json:"io,omitempty"` 36 37 // 源站下载入口 38 IoSrcHost string `json:"io_src,omitempty"` 39 } 40 41 type RegionID string 42 43 // GetDefaultReion 根据RegionID获取对应的Region信息 44 func GetRegionByID(regionID RegionID) (Region, bool) { 45 if r, ok := regionMap[regionID]; ok { 46 return r, ok 47 } 48 return Region{}, false 49 } 50 51 func (r *Region) String() string { 52 str := "" 53 str += fmt.Sprintf("SrcUpHosts: %v\n", r.SrcUpHosts) 54 str += fmt.Sprintf("CdnUpHosts: %v\n", r.CdnUpHosts) 55 str += fmt.Sprintf("IovipHost: %s\n", r.IovipHost) 56 str += fmt.Sprintf("RsHost: %s\n", r.RsHost) 57 str += fmt.Sprintf("RsfHost: %s\n", r.RsfHost) 58 str += fmt.Sprintf("ApiHost: %s\n", r.ApiHost) 59 return str 60 } 61 62 func endpoint(useHttps bool, host string) string { 63 host = strings.TrimSpace(host) 64 if host == "" { 65 return "" 66 } 67 68 if strings.HasPrefix(host, "http://") || 69 strings.HasPrefix(host, "https://") { 70 return host 71 } 72 73 scheme := "http://" 74 if useHttps { 75 scheme = "https://" 76 } 77 return fmt.Sprintf("%s%s", scheme, host) 78 } 79 80 // 获取rsfHost 81 func (r *Region) GetRsfHost(useHttps bool) string { 82 return endpoint(useHttps, r.RsfHost) 83 } 84 85 // 获取io host 86 func (r *Region) GetIoHost(useHttps bool) string { 87 return endpoint(useHttps, r.IovipHost) 88 } 89 90 // 获取RsHost 91 func (r *Region) GetRsHost(useHttps bool) string { 92 return endpoint(useHttps, r.RsHost) 93 } 94 95 // 获取api host 96 func (r *Region) GetApiHost(useHttps bool) string { 97 return endpoint(useHttps, r.ApiHost) 98 } 99 100 func (r *Region) GetRegions(ctx context.Context) ([]*region_v2.Region, error) { 101 newRegion := ®ion_v2.Region{ 102 Up: region_v2.Endpoints{Preferred: append(r.CdnUpHosts, r.SrcUpHosts...)}, 103 } 104 if host := r.IovipHost; host != "" { 105 newRegion.Io = region_v2.Endpoints{Preferred: []string{host}} 106 } 107 if host := r.IoSrcHost; host != "" { 108 newRegion.IoSrc = region_v2.Endpoints{Preferred: []string{host}} 109 } 110 if host := r.RsHost; host != "" { 111 newRegion.Rs = region_v2.Endpoints{Preferred: []string{host}} 112 } 113 if host := r.RsfHost; host != "" { 114 newRegion.Rsf = region_v2.Endpoints{Preferred: []string{host}} 115 } 116 if host := r.ApiHost; host != "" { 117 newRegion.Api = region_v2.Endpoints{Preferred: []string{host}} 118 } 119 // 此包需要使用 ucHosts 作为 v2 包中的 uc 域名 120 // ucHosts 用户可通过 SetUcHosts 自定义 121 newRegion.Bucket = region_v2.Endpoints{Preferred: getUCHosts()} 122 return []*region_v2.Region{newRegion}, nil 123 } 124 125 var ( 126 // regionHuadong 表示华东机房 127 regionHuadong = Region{ 128 SrcUpHosts: []string{ 129 "up.qiniup.com", 130 }, 131 CdnUpHosts: []string{ 132 "upload.qiniup.com", 133 }, 134 RsHost: "rs.qbox.me", 135 RsfHost: "rsf.qbox.me", 136 ApiHost: "api.qiniu.com", 137 IovipHost: "iovip.qbox.me", 138 } 139 140 // regionHuadongZhejiang2 表示华东-浙江2 141 regionHuadongZhejiang2 = Region{ 142 SrcUpHosts: []string{ 143 "up-cn-east-2.qiniup.com", 144 }, 145 CdnUpHosts: []string{ 146 "upload-cn-east-2.qiniup.com", 147 }, 148 RsHost: "rs-cn-east-2.qiniuapi.com", 149 RsfHost: "rsf-cn-east-2.qiniuapi.com", 150 ApiHost: "api-cn-east-2.qiniuapi.com", 151 IovipHost: "iovip-cn-east-2.qiniuio.com", 152 } 153 154 // regionHuabei 表示华北机房 155 regionHuabei = Region{ 156 SrcUpHosts: []string{ 157 "up-z1.qiniup.com", 158 }, 159 CdnUpHosts: []string{ 160 "upload-z1.qiniup.com", 161 }, 162 RsHost: "rs-z1.qbox.me", 163 RsfHost: "rsf-z1.qbox.me", 164 ApiHost: "api-z1.qiniuapi.com", 165 IovipHost: "iovip-z1.qbox.me", 166 } 167 168 // regionHuanan 表示华南机房 169 regionHuanan = Region{ 170 SrcUpHosts: []string{ 171 "up-z2.qiniup.com", 172 }, 173 CdnUpHosts: []string{ 174 "upload-z2.qiniup.com", 175 }, 176 RsHost: "rs-z2.qbox.me", 177 RsfHost: "rsf-z2.qbox.me", 178 ApiHost: "api-z2.qiniuapi.com", 179 IovipHost: "iovip-z2.qbox.me", 180 } 181 182 // regionNorthAmerica 表示北美机房 183 regionNorthAmerica = Region{ 184 SrcUpHosts: []string{ 185 "up-na0.qiniup.com", 186 }, 187 CdnUpHosts: []string{ 188 "upload-na0.qiniup.com", 189 }, 190 RsHost: "rs-na0.qbox.me", 191 RsfHost: "rsf-na0.qbox.me", 192 ApiHost: "api-na0.qiniuapi.com", 193 IovipHost: "iovip-na0.qbox.me", 194 } 195 196 // regionSingapore 表示新加坡机房 197 regionSingapore = Region{ 198 SrcUpHosts: []string{ 199 "up-as0.qiniup.com", 200 }, 201 CdnUpHosts: []string{ 202 "upload-as0.qiniup.com", 203 }, 204 RsHost: "rs-as0.qbox.me", 205 RsfHost: "rsf-as0.qbox.me", 206 ApiHost: "api-as0.qiniuapi.com", 207 IovipHost: "iovip-as0.qbox.me", 208 } 209 ) 210 211 const ( 212 // region code 213 RIDHuadong = RegionID("z0") 214 RIDHuadongZheJiang2 = RegionID("cn-east-2") 215 RIDHuabei = RegionID("z1") 216 RIDHuanan = RegionID("z2") 217 RIDNorthAmerica = RegionID("na0") 218 RIDSingapore = RegionID("as0") 219 ) 220 221 // regionMap 是RegionID到具体的Region的映射 222 var regionMap = map[RegionID]Region{ 223 RIDHuadong: regionHuadong, 224 RIDHuadongZheJiang2: regionHuadongZhejiang2, 225 RIDHuanan: regionHuanan, 226 RIDHuabei: regionHuabei, 227 RIDSingapore: regionSingapore, 228 RIDNorthAmerica: regionNorthAmerica, 229 } 230 231 const ( 232 defaultUcHost0 = "uc.qiniuapi.com" 233 defaultUcHost1 = "kodo-config.qiniuapi.com" 234 defaultUcHost2 = "uc.qbox.me" 235 ) 236 237 // UcHost 为查询空间相关域名的 API 服务地址 238 // 设置 UcHost 时,如果不指定 scheme 默认会使用 https 239 // Deprecated 使用 SetUcHosts 替换 240 var UcHost = "" 241 242 var ( 243 ucHostsLock sync.RWMutex 244 ucHosts = []string{defaultUcHost0, defaultUcHost1, defaultUcHost2} 245 ) 246 247 func init() { 248 if defaultUcHosts, err := defaults.BucketURLs(); err == nil && len(defaultUcHosts) > 0 { 249 SetUcHosts(defaultUcHosts...) 250 } 251 } 252 253 // SetUcHost 254 // Deprecated 使用 SetUcHosts 替换 255 func SetUcHost(host string, useHttps bool) { 256 if len(host) == 0 { 257 return 258 } 259 host = endpoint(useHttps, host) 260 SetUcHosts(host) 261 } 262 263 // SetUcHosts 配置多个 UC 域名 264 func SetUcHosts(hosts ...string) { 265 var newHosts []string 266 for _, host := range hosts { 267 if len(host) > 0 { 268 newHosts = append(newHosts, host) 269 } 270 } 271 272 ucHostsLock.Lock() 273 defer ucHostsLock.Unlock() 274 ucHosts = newHosts 275 } 276 277 func getUCHosts() []string { 278 ucHostsLock.RLock() 279 defer ucHostsLock.RUnlock() 280 281 hosts := make([]string, 0, len(ucHosts)) 282 for _, host := range ucHosts { 283 if len(host) > 0 { 284 hosts = append(hosts, host) 285 } 286 } 287 return hosts 288 } 289 290 func getUcEndpointProvider(useHttps bool, hosts []string) region_v2.EndpointsProvider { 291 if len(hosts) == 0 { 292 if len(UcHost) > 0 { 293 hosts = append(hosts, endpoint(useHttps, UcHost)) 294 } 295 296 oldHosts := getUCHosts() 297 for _, host := range oldHosts { 298 hosts = append(hosts, endpoint(useHttps, host)) 299 } 300 } 301 302 if len(hosts) > 0 { 303 return region_v2.Endpoints{Preferred: hosts} 304 } else { 305 return nil 306 } 307 } 308 309 func getUcEndpoint(useHttps bool, hosts []string) region_v2.Endpoints { 310 provider := getUcEndpointProvider(useHttps, hosts) 311 if provider == nil { 312 return region_v2.Endpoints{} 313 } 314 315 if p, ok := provider.(region_v2.Endpoints); ok { 316 return p 317 } else { 318 return region_v2.Endpoints{} 319 } 320 } 321 322 // GetRegion 用来根据ak和bucket来获取空间相关的机房信息 323 // 延用 v2, v2 结构和 v4 结构不同且暂不可替代 324 // Deprecated 使用 GetRegionWithOptions 替换 325 func GetRegion(ak, bucket string) (*Region, error) { 326 return GetRegionWithOptions(ak, bucket, DefaultUCApiOptions()) 327 } 328 329 // GetRegionWithOptions 用来根据ak和bucket来获取空间相关的机房信息 330 func GetRegionWithOptions(ak, bucket string, options UCApiOptions) (*Region, error) { 331 return getRegionByV2(ak, bucket, options) 332 } 333 334 // 使用 v4 335 // 336 //lint:ignore U1000 Used by test case 337 func getRegionGroup(ak, bucket string) (*RegionGroup, error) { 338 return getRegionByV4(ak, bucket, DefaultUCApiOptions()) 339 } 340 341 func getRegionGroupWithOptions(ak, bucket string, options UCApiOptions) (*RegionGroup, error) { 342 return getRegionByV4(ak, bucket, options) 343 } 344 345 type RegionInfo struct { 346 ID string `json:"id"` 347 Description string `json:"description"` 348 } 349 350 func SetRegionCachePath(newPath string) { 351 setRegionV2CachePath(newPath) 352 setRegionV4CachePath(newPath) 353 } 354 355 // GetRegionsInfo Deprecated and use GetRegionsInfoWithOptions instead 356 // Deprecated 357 func GetRegionsInfo(mac *auth.Credentials) ([]RegionInfo, error) { 358 return GetRegionsInfoWithOptions(mac, DefaultUCApiOptions()) 359 } 360 361 func GetRegionsInfoWithOptions(mac *auth.Credentials, options UCApiOptions) ([]RegionInfo, error) { 362 var httpClient clientv2.Client 363 if options.Client != nil { 364 httpClient = options.Client.Client 365 } 366 367 if mac == nil { 368 mac = auth.Default() 369 } 370 371 response, err := apis.NewStorage(&http_client.Options{ 372 BasicHTTPClient: httpClient, 373 HostFreezeDuration: options.HostFreezeDuration, 374 HostRetryConfig: &clientv2.RetryConfig{ 375 RetryMax: options.RetryMax, 376 }, 377 }).GetRegions( 378 context.Background(), 379 &apis.GetRegionsRequest{Credentials: mac}, 380 &apis.Options{OverwrittenBucketHosts: getUcEndpointProvider(options.UseHttps, options.Hosts)}, 381 ) 382 if err != nil { 383 return nil, err 384 } 385 386 regions := make([]RegionInfo, 0, len(response.Regions)) 387 for _, region := range response.Regions { 388 regions = append(regions, RegionInfo{ 389 ID: region.Id, 390 Description: region.Description, 391 }) 392 } 393 return regions, nil 394 }