github.com/qiniu/go-sdk/v7@v7.27.0/storage/uc.go (about) 1 // package storage 提供了用户存储配置(uc)方面的功能, 定义了UC API 的返回结构体类型 2 package storage 3 4 import ( 5 "context" 6 "net/url" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/qiniu/go-sdk/v7/storagev2/apis" 12 "github.com/qiniu/go-sdk/v7/storagev2/apis/get_bucket_event_rules" 13 "github.com/qiniu/go-sdk/v7/storagev2/apis/get_bucket_info" 14 "github.com/qiniu/go-sdk/v7/storagev2/apis/get_bucket_infos" 15 "github.com/qiniu/go-sdk/v7/storagev2/apis/set_bucket_cors_rules" 16 "github.com/qiniu/go-sdk/v7/storagev2/apis/set_bucket_taggings" 17 ) 18 19 // BucketSummary 存储空间信息 20 type BucketSummary struct { 21 // 存储空间名字 22 Name string `json:"name"` 23 Info BucketInfo `json:"info"` 24 } 25 26 // BucketInfo 存储空间的详细信息 27 type BucketInfo struct { 28 // 镜像回源地址, 接口返回的多个地址以;分割 29 Source string `json:"source"` 30 31 // 镜像回源的时候请求头中的HOST 32 Host string `json:"host"` 33 34 // 镜像回源地址过期时间(秒数), 现在这个功能没有实现,因此这个字段现在是没有意义的 35 Expires int `json:"expires"` 36 37 // 是否开启了原图保护 38 Protected int `json:"protected"` 39 40 // 是否是私有空间 41 Private int `json:"private"` 42 43 // 如果NoIndexPage是false表示开启了空间根目录index.html 44 // 如果是true, 表示没有开启 45 // 开启了根目录下的index.html, 文件将会被作为默认首页展示 46 NoIndexPage int `json:"no_index_page"` 47 48 // 在规定的时效内使客户端缓存更新的效果 49 MaxAge int `json:"max_age"` 50 51 // 图片样式分隔符, 接口返回的可能有多个 52 Separator string `json:"separator"` 53 54 // 图片样式, map中的key表示图片样式命令名字 55 // map中的value表示图片样式命令的内容 56 Styles map[string]string `json:"styles"` 57 58 // 防盗链模式 59 // 1 - 表示设置了防盗链的referer白名单 60 // 2 - 表示设置了防盗链的referer黑名单 61 AntiLeechMode int `json:"anti_leech_mode"` 62 63 // 使用token签名进行防盗链 64 // 0 - 表示关闭 65 // 1 - 表示开启 66 TokenAntiLeechMode int `json:"token_anti_leech"` 67 68 // 防盗链referer白名单列表 69 ReferWl []string `json:"refer_wl"` 70 71 // 防盗链referer黑名单列表 72 ReferBl []string `json:"refer_bl"` 73 74 // 在源站支持的情况下开启源站的Referer防盗链 75 EnableSource bool `json:"source_enabled"` 76 77 // 是否允许空的referer访问 78 NoRefer bool `json:"no_refer"` 79 80 // 用于防盗链token的生成 81 MacKey string `json:"mac_key"` 82 83 // 用于防盗链token的生成 84 MacKey2 string `json:"mac_key2"` 85 86 // 存储区域, 兼容保留 87 Zone string 88 89 // 存储区域 90 Region string 91 92 // 空间备注信息 93 Remark string 94 95 // 空间创建时间 96 // 当服务端未返回该字段时为零值,可通过 Ctime.IsZero() 判断 97 Ctime time.Time 98 } 99 100 // ReferAntiLeechConfig 是用户存储空间的Refer防盗链配置 101 type ReferAntiLeechConfig struct { 102 // 防盗链模式, 0 - 关闭Refer防盗链, 1 - 开启Referer白名单,2 - 开启Referer黑名单 103 Mode int 104 105 // 是否允许空的referer访问 106 AllowEmptyReferer bool 107 108 // Pattern 匹配HTTP Referer头, 当模式是1或者2的时候有效 109 // Mode为1的时候表示允许Referer符合该Pattern的HTTP请求访问 110 // Mode为2的时候表示禁止Referer符合该Pattern的HTTP请求访问 111 // 当前允许的匹配字符串格式分为三种: 112 // 一种为空主机头域名, 比如 foo.com; 一种是泛域名, 比如 *.bar.com; 113 // 一种是完全通配符, 即一个 *; 114 // 多个规则之间用;隔开, 比如: foo.com;*.bar.com;sub.foo.com;*.sub.bar.com 115 Pattern string 116 117 // 是否开启源站的防盗链, 默认为0, 只开启CDN防盗链, 当设置为1的时候 118 // 在源站支持的情况下开启源站的Referer防盗链 119 EnableSource bool 120 } 121 122 // SetMode 设置referer防盗链模式 123 func (r *ReferAntiLeechConfig) SetMode(mode int) *ReferAntiLeechConfig { 124 if mode != 0 && mode != 1 && mode != 2 { 125 panic("Referer anti_leech_mode must be in [0, 1, 2]") 126 } 127 r.Mode = mode 128 return r 129 } 130 131 // SetEmptyReferer 设置是否允许空Referer访问 132 func (r *ReferAntiLeechConfig) SetEmptyReferer(enable bool) *ReferAntiLeechConfig { 133 r.AllowEmptyReferer = enable 134 return r 135 } 136 137 // SetPattern 设置匹配Referer的模式 138 func (r *ReferAntiLeechConfig) SetPattern(pattern string) *ReferAntiLeechConfig { 139 if pattern == "" { 140 panic("Empty pattern is not allowed") 141 } 142 143 r.Pattern = pattern 144 return r 145 } 146 147 // AddDomainPattern 添加pattern到Pattern字段 148 // 假入Pattern值为"*.qiniu.com", 使用AddDomainPattern("*.baidu.com")后 149 // r.Pattern的值为"*.qiniu.com;*.baidu.com" 150 func (r *ReferAntiLeechConfig) AddDomainPattern(pattern string) *ReferAntiLeechConfig { 151 if strings.HasSuffix(r.Pattern, ";") { 152 r.Pattern = strings.TrimRight(r.Pattern, ";") 153 } 154 r.Pattern = strings.Join([]string{r.Pattern, pattern}, ";") 155 return r 156 } 157 158 // SetEnableSource 设置是否开启源站的防盗链 159 func (r *ReferAntiLeechConfig) SetEnableSource(enable bool) *ReferAntiLeechConfig { 160 r.EnableSource = enable 161 return r 162 } 163 164 // AsQueryString 编码成query参数格式 165 func (r *ReferAntiLeechConfig) AsQueryString() string { 166 params := make(url.Values, 4) 167 params.Add("mode", strconv.Itoa(r.Mode)) 168 params.Add("pattern", r.Pattern) 169 if r.AllowEmptyReferer { 170 params.Add("norefer", "1") 171 } else { 172 params.Add("norefer", "0") 173 } 174 if r.EnableSource { 175 params.Add("source_enabled", "1") 176 } else { 177 params.Add("source_enabled", "0") 178 } 179 return params.Encode() 180 } 181 182 // ProtectedOn 返回true or false 183 // 如果开启了原图保护,返回true, 否则false 184 func (b *BucketInfo) ProtectedOn() bool { 185 return b.Protected == 1 186 } 187 188 // IsPrivate 返回布尔值 189 // 如果是私有空间, 返回 true, 否则返回false 190 func (b *BucketInfo) IsPrivate() bool { 191 return b.Private == 1 192 } 193 194 // ImageSources 返回多个镜像回源地址的列表 195 func (b *BucketInfo) ImageSources() (srcs []string) { 196 srcs = strings.Split(b.Source, ";") 197 return 198 } 199 200 // IndexPageOn 返回空间是否开启了根目录下的index.html 201 func (b *BucketInfo) IndexPageOn() bool { 202 return b.NoIndexPage == 0 203 } 204 205 // Separators 返回分隔符列表 206 func (b *BucketInfo) Separators() (ret []rune) { 207 for _, r := range b.Separator { 208 ret = append(ret, r) 209 } 210 return 211 } 212 213 // WhiteListSet 是否设置了防盗链白名单 214 func (b *BucketInfo) WhiteListSet() bool { 215 return b.AntiLeechMode == 1 216 } 217 218 // BlackListSet 是否设置了防盗链黑名单 219 func (b *BucketInfo) BlackListSet() bool { 220 return b.AntiLeechMode == 2 221 } 222 223 // TokenAntiLeechModeOn 返回是否使用token签名防盗链开启了 224 func (b *BucketInfo) TokenAntiLeechModeOn() bool { 225 return b.TokenAntiLeechMode == 1 226 } 227 228 // parseBucketCreatedAt 解析服务端返回的 CreatedAt 字符串;空字符串视为零值(无错误) 229 func parseBucketCreatedAt(createdAt string) (time.Time, error) { 230 if createdAt == "" { 231 return time.Time{}, nil 232 } 233 return time.Parse(time.RFC3339, createdAt) 234 } 235 236 // GetBucketInfo 返回BucketInfo结构 237 func (m *BucketManager) GetBucketInfo(bucketName string) (BucketInfo, error) { 238 toBucketInfo := func(bucketInfo *get_bucket_info.Response) (BucketInfo, error) { 239 ctime, err := parseBucketCreatedAt(bucketInfo.CreatedAt) 240 if err != nil { 241 return BucketInfo{}, err 242 } 243 return BucketInfo{ 244 Source: bucketInfo.Source, 245 Host: bucketInfo.Host, 246 Expires: int(bucketInfo.Expires), 247 Protected: int(bucketInfo.Protected), 248 Private: int(bucketInfo.Private), 249 NoIndexPage: int(bucketInfo.NoIndexPage), 250 MaxAge: int(bucketInfo.MaxAge), 251 Separator: bucketInfo.Separator, 252 Styles: bucketInfo.Styles, 253 AntiLeechMode: int(bucketInfo.AntiLeechMode), 254 TokenAntiLeechMode: int(bucketInfo.TokenAntiLeech), 255 ReferWl: bucketInfo.ReferWl, 256 ReferBl: bucketInfo.ReferBl, 257 EnableSource: bucketInfo.SourceEnabled, 258 NoRefer: bucketInfo.NoReferer, 259 MacKey: bucketInfo.MacKey, 260 MacKey2: bucketInfo.MacKey2, 261 Zone: bucketInfo.Zone, 262 Region: bucketInfo.Region, 263 Remark: bucketInfo.Remark, 264 Ctime: ctime, 265 }, nil 266 } 267 response, err := m.apiClient.GetBucketInfo( 268 context.Background(), 269 &apis.GetBucketInfoRequest{ 270 Bucket: bucketName, 271 }, 272 m.makeRequestOptions()) 273 if err != nil { 274 return BucketInfo{}, err 275 } 276 return toBucketInfo(response) 277 } 278 279 // SetRemark 设置空间备注信息 280 func (m *BucketManager) SetRemark(bucketName, remark string) error { 281 _, err := m.apiClient.SetBucketRemark( 282 context.Background(), 283 &apis.SetBucketRemarkRequest{ 284 Bucket: bucketName, 285 Remark: remark, 286 }, 287 m.makeRequestOptions(), 288 ) 289 return err 290 } 291 292 // BucketInfosForRegion 获取指定区域的该用户的所有bucketInfo信息 293 func (m *BucketManager) BucketInfosInRegion(region RegionID, statistics bool) (bucketInfos []BucketSummary, err error) { 294 toBucketInfo := func(bucketInfo *get_bucket_infos.BucketInfoV2) (BucketInfo, error) { 295 ctime, err := parseBucketCreatedAt(bucketInfo.CreatedAt) 296 if err != nil { 297 return BucketInfo{}, err 298 } 299 return BucketInfo{ 300 Source: bucketInfo.Source, 301 Host: bucketInfo.Host, 302 Expires: int(bucketInfo.Expires), 303 Protected: int(bucketInfo.Protected), 304 Private: int(bucketInfo.Private), 305 NoIndexPage: int(bucketInfo.NoIndexPage), 306 MaxAge: int(bucketInfo.MaxAge), 307 Separator: bucketInfo.Separator, 308 Styles: bucketInfo.Styles, 309 AntiLeechMode: int(bucketInfo.AntiLeechMode), 310 TokenAntiLeechMode: int(bucketInfo.TokenAntiLeech), 311 ReferWl: bucketInfo.ReferWl, 312 ReferBl: bucketInfo.ReferBl, 313 EnableSource: bucketInfo.SourceEnabled, 314 NoRefer: bucketInfo.NoReferer, 315 MacKey: bucketInfo.MacKey, 316 MacKey2: bucketInfo.MacKey2, 317 Zone: bucketInfo.Zone, 318 Region: bucketInfo.Region, 319 Remark: bucketInfo.Remark, 320 Ctime: ctime, 321 }, nil 322 } 323 response, err := m.apiClient.GetBucketInfos( 324 context.Background(), 325 &apis.GetBucketInfosRequest{ 326 Region: string(region), 327 Statistics: statistics, 328 }, 329 m.makeRequestOptions(), 330 ) 331 if err != nil { 332 return nil, err 333 } 334 summaries := make([]BucketSummary, 0, len(response.AllBucketInfosV2)) 335 for _, b := range response.AllBucketInfosV2 { 336 bucketInfo, err := toBucketInfo(&b.BucketInfo) 337 if err != nil { 338 return nil, err 339 } 340 summaries = append(summaries, BucketSummary{ 341 Name: b.Name, 342 Info: bucketInfo, 343 }) 344 } 345 return summaries, nil 346 } 347 348 // SetReferAntiLeechMode 配置存储空间referer防盗链模式 349 func (m *BucketManager) SetReferAntiLeechMode(bucketName string, refererAntiLeechConfig *ReferAntiLeechConfig) error { 350 var allowEmptyReferer, enableSource int64 351 if refererAntiLeechConfig.AllowEmptyReferer { 352 allowEmptyReferer = 1 353 } 354 if refererAntiLeechConfig.EnableSource { 355 enableSource = 1 356 } 357 _, err := m.apiClient.SetBucketReferAntiLeech( 358 context.Background(), 359 &apis.SetBucketReferAntiLeechRequest{ 360 Bucket: bucketName, 361 Mode: int64(refererAntiLeechConfig.Mode), 362 Pattern: refererAntiLeechConfig.Pattern, 363 AllowEmptyReferer: allowEmptyReferer, 364 SourceEnabled: enableSource, 365 }, 366 m.makeRequestOptions(), 367 ) 368 return err 369 } 370 371 // BucketLifeCycleRule 定义了关于七牛存储空间关于生命周期的一些配置,规则。 372 // 比如存储空间中文件可以设置多少天后删除,多少天后转低频存储等等 373 type BucketLifeCycleRule struct { 374 // 规则名称, 在设置的bucket中规则名称需要是唯一的 375 // 同时长度小于50, 不能为空 376 // 由字母,数字和下划线组成 377 Name string `json:"name"` 378 379 // 以该前缀开头的文件应用此规则 380 Prefix string `json:"prefix"` 381 382 // 指定存储空间内的文件多少天后删除 383 // 0 - 不删除 384 // > 0 表示多少天后删除 385 DeleteAfterDays int `json:"delete_after_days"` 386 387 // 在多少天后转低频存储 388 // 0 - 表示不转低频 389 // > 0 表示多少天后转低频存储 390 ToLineAfterDays int `json:"to_line_after_days"` 391 392 // 指定文件上传多少天后转归档直读存储。 393 // 0 表示不转归档直读存储, 394 // > 0 表示多少天后转归档直读存储 395 ToArchiveIRAfterDays int `json:"to_archive_ir_after_days"` 396 397 // 指定文件上传多少天后转归档存储。 398 // 0 表示不转归档存储, 399 // > 0 表示多少天后转归档存储 400 ToArchiveAfterDays int `json:"to_archive_after_days"` 401 402 // 指定文件上传多少天后转深度归档存储。 403 // 0 表示不转深度归档存储 404 // > 0 表示多少天后转深度归档存储 405 ToDeepArchiveAfterDays int `json:"to_deep_archive_after_days"` 406 } 407 408 // SetBucketLifeCycleRule 设置存储空间内文件的生命周期规则 409 func (m *BucketManager) AddBucketLifeCycleRule(bucketName string, lifeCycleRule *BucketLifeCycleRule) error { 410 _, err := m.apiClient.AddBucketRules( 411 context.Background(), 412 &apis.AddBucketRulesRequest{ 413 Bucket: bucketName, 414 Name: lifeCycleRule.Name, 415 Prefix: lifeCycleRule.Prefix, 416 DeleteAfterDays: int64(lifeCycleRule.DeleteAfterDays), 417 ToIaAfterDays: int64(lifeCycleRule.ToLineAfterDays), 418 ToArchiveAfterDays: int64(lifeCycleRule.ToArchiveAfterDays), 419 ToArchiveIrAfterDays: int64(lifeCycleRule.ToArchiveIRAfterDays), 420 ToDeepArchiveAfterDays: int64(lifeCycleRule.ToDeepArchiveAfterDays), 421 }, 422 m.makeRequestOptions(), 423 ) 424 return err 425 } 426 427 // DelBucketLifeCycleRule 删除特定存储空间上设定的规则 428 func (m *BucketManager) DelBucketLifeCycleRule(bucketName, ruleName string) error { 429 _, err := m.apiClient.DeleteBucketRules( 430 context.Background(), 431 &apis.DeleteBucketRulesRequest{ 432 Bucket: bucketName, 433 Name: ruleName, 434 }, 435 m.makeRequestOptions(), 436 ) 437 return err 438 } 439 440 // UpdateBucketLifeCycleRule 更新特定存储空间上的生命周期规则 441 func (m *BucketManager) UpdateBucketLifeCycleRule(bucketName string, rule *BucketLifeCycleRule) error { 442 _, err := m.apiClient.UpdateBucketRules( 443 context.Background(), 444 &apis.UpdateBucketRulesRequest{ 445 Bucket: bucketName, 446 Name: rule.Name, 447 Prefix: rule.Prefix, 448 DeleteAfterDays: int64(rule.DeleteAfterDays), 449 ToIaAfterDays: int64(rule.ToLineAfterDays), 450 ToArchiveAfterDays: int64(rule.ToArchiveAfterDays), 451 ToArchiveIrAfterDays: int64(rule.ToArchiveIRAfterDays), 452 ToDeepArchiveAfterDays: int64(rule.ToDeepArchiveAfterDays), 453 }, 454 m.makeRequestOptions(), 455 ) 456 return err 457 } 458 459 // GetBucketLifeCycleRule 获取指定空间上设置的生命周期规则 460 func (m *BucketManager) GetBucketLifeCycleRule(bucketName string) ([]BucketLifeCycleRule, error) { 461 response, err := m.apiClient.GetBucketRules( 462 context.Background(), 463 &apis.GetBucketRulesRequest{ 464 Bucket: bucketName, 465 }, 466 m.makeRequestOptions(), 467 ) 468 if err != nil { 469 return nil, err 470 } 471 rules := make([]BucketLifeCycleRule, 0, len(response.BucketRules)) 472 for _, rule := range response.BucketRules { 473 rules = append(rules, BucketLifeCycleRule{ 474 Name: rule.Name, 475 Prefix: rule.Prefix, 476 DeleteAfterDays: int(rule.DeleteAfterDays), 477 ToLineAfterDays: int(rule.ToIaAfterDays), 478 ToArchiveAfterDays: int(rule.ToArchiveAfterDays), 479 ToDeepArchiveAfterDays: int(rule.ToDeepArchiveAfterDays), 480 }) 481 } 482 return rules, nil 483 } 484 485 // BucketEnvent 定义了存储空间发生事件时候的通知规则 486 // 比如调用了存储的"delete"删除接口删除文件, 这个是一个事件; 487 // 当这个事件发生的时候, 我们要对哪些文件,做什么处理,是否要作回调, 488 // 都可以通过这个结构体配置 489 type BucketEventRule struct { 490 // 规则名字 491 Name string `json:"name"` 492 493 // 匹配文件前缀 494 Prefix string `json:"prefix"` 495 496 // 匹配文件后缀 497 Suffix string `json:"suffix"` 498 499 // 事件类型 500 // put,mkfile,delete,copy,move,append,disable,enable,deleteMarkerCreate 501 Event []string `json:"event"` 502 503 // 回调通知地址, 可以指定多个 504 CallbackURL []string `json:"callback_urls"` 505 506 // 用户的AccessKey, 可选, 设置的话会对通知请求用对应的ak、sk进行签名 507 AccessKey string `json:"access_key"` 508 509 // 回调通知的请求HOST, 可选 510 Host string `json:"host"` 511 } 512 513 // Params 返回一个hash结构 514 func (r *BucketEventRule) Params(bucket string) map[string][]string { 515 params := make(map[string][]string) 516 517 params["bucket"] = []string{bucket} 518 params["name"] = []string{r.Name} 519 if r.Prefix != "" { 520 params["prefix"] = []string{r.Prefix} 521 } 522 if r.Suffix != "" { 523 params["suffix"] = []string{r.Suffix} 524 } 525 params["event"] = r.Event 526 params["callbackURL"] = r.CallbackURL 527 if r.AccessKey != "" { 528 params["access_key"] = []string{r.AccessKey} 529 } 530 if r.Host != "" { 531 params["host"] = []string{r.Host} 532 } 533 return params 534 } 535 536 // AddBucketEvent 增加存储空间事件通知规则 537 func (m *BucketManager) AddBucketEvent(bucket string, rule *BucketEventRule) error { 538 _, err := m.apiClient.AddBucketEventRule( 539 context.Background(), 540 &apis.AddBucketEventRuleRequest{ 541 Bucket: bucket, 542 Name: rule.Name, 543 Prefix: rule.Prefix, 544 Suffix: rule.Suffix, 545 EventTypes: rule.Event, 546 CallbackUrls: rule.CallbackURL, 547 AccessKey: rule.AccessKey, 548 Host: rule.Host, 549 }, 550 m.makeRequestOptions(), 551 ) 552 return err 553 } 554 555 // DelBucketEvent 删除指定存储空间的通知事件规则 556 func (m *BucketManager) DelBucketEvent(bucket, ruleName string) error { 557 _, err := m.apiClient.DeleteBucketEventRule( 558 context.Background(), 559 &apis.DeleteBucketEventRuleRequest{ 560 Bucket: bucket, 561 Name: ruleName, 562 }, 563 m.makeRequestOptions(), 564 ) 565 return err 566 } 567 568 // UpdateBucketEnvent 更新指定存储空间的事件通知规则 569 func (m *BucketManager) UpdateBucketEnvent(bucket string, rule *BucketEventRule) error { 570 _, err := m.apiClient.UpdateBucketEventRule( 571 context.Background(), 572 &apis.UpdateBucketEventRuleRequest{ 573 Bucket: bucket, 574 Name: rule.Name, 575 Prefix: rule.Prefix, 576 Suffix: rule.Suffix, 577 EventTypes: rule.Event, 578 CallbackUrls: rule.CallbackURL, 579 AccessKey: rule.AccessKey, 580 Host: rule.Host, 581 }, 582 m.makeRequestOptions(), 583 ) 584 return err 585 } 586 587 // GetBucketEvent 获取指定存储空间的事件通知规则 588 func (m *BucketManager) GetBucketEvent(bucket string) ([]BucketEventRule, error) { 589 toBucketEventRule := func(rule *get_bucket_event_rules.BucketEventRule) BucketEventRule { 590 return BucketEventRule{ 591 Name: rule.Name, 592 Prefix: rule.Prefix, 593 Suffix: rule.Suffix, 594 Event: rule.EventTypes, 595 CallbackURL: rule.CallbackUrls, 596 AccessKey: rule.AccessKey, 597 Host: rule.Host, 598 } 599 } 600 response, err := m.apiClient.GetBucketEventRules( 601 context.Background(), 602 &apis.GetBucketEventRulesRequest{ 603 Bucket: bucket, 604 }, 605 m.makeRequestOptions(), 606 ) 607 if err != nil { 608 return nil, err 609 } 610 rules := make([]BucketEventRule, 0, len(response.BucketEventRules)) 611 for _, r := range response.BucketEventRules { 612 rules = append(rules, toBucketEventRule(&r)) 613 } 614 return rules, err 615 } 616 617 // CorsRule 是关于存储的跨域规则 618 // 最多允许设置10条跨域规则 619 // 对于同一个域名如果设置了多条规则,那么按顺序使用第一条匹配的规则去生成返回值。 620 // 对于简单跨域请求,只匹配 Origin; 621 // 对于预检请求, 需要匹配 Origin、AllowedMethod、AllowedHeader; 622 623 // 如果没有设置任何corsRules,那么默认允许所有的跨域请求 624 // 参考: https://www.w3.org/TR/cors/ 625 type CorsRule struct { 626 // allowed_orgin: 允许的域名。必填;支持通配符*;*表示全部匹配;只有第一个*生效;需要设置"Scheme";大小写敏感。例如 627 // 规则:http://*.abc.*.com 请求:"http://test.abc.test.com" 结果:不通过 628 // 规则:"http://abc.com" 请求:"https://abc.com"/"abc.com" 结果:不通过 629 // 规则:"abc.com" 请求:"http://abc.com" 结果:不通过 630 AllowedOrigin []string `json:"allowed_origin"` 631 632 // allowed_method: 允许的方法。必填;不支持通配符;大小写不敏感; 633 AllowedMethod []string `json:"allowed_method"` 634 635 // allowed_header: 允许的header。选填;支持通配符*,但只能是单独的*,表示允许全部header,其他*不生效;空则不允许任何header;大小写不敏感; 636 AllowedHeader []string `json:"allowed_header"` 637 638 // 暴露的header。选填;不支持通配符;X-Log, X-Reqid是默认会暴露的两个header;其他的header如果没有设置,则不会暴露;大小写不敏感; 639 ExposedHeader []string `json:"exposed_header"` 640 641 // max_age: 结果可以缓存的时间。选填;空则不缓存 642 MaxAge int64 `json:"max_age"` 643 } 644 645 // AddCorsRules 设置指定存储空间的跨域规则 646 func (m *BucketManager) AddCorsRules(bucket string, corsRules []CorsRule) error { 647 rules := make(set_bucket_cors_rules.CORSRules, 0, len(corsRules)) 648 for _, rule := range corsRules { 649 rules = append(rules, set_bucket_cors_rules.CORSRule{ 650 AllowedOrigin: rule.AllowedMethod, 651 AllowedMethod: rule.AllowedMethod, 652 AllowedHeader: rule.AllowedHeader, 653 ExposedHeader: rule.ExposedHeader, 654 MaxAge: rule.MaxAge, 655 }) 656 } 657 _, err := m.apiClient.SetBucketCORSRules( 658 context.Background(), 659 &apis.SetBucketCORSRulesRequest{ 660 Bucket: bucket, 661 CORSRules: rules, 662 }, 663 m.makeRequestOptions(), 664 ) 665 return err 666 } 667 668 // GetCorsRules 获取指定存储空间的跨域规则 669 func (m *BucketManager) GetCorsRules(bucket string) ([]CorsRule, error) { 670 response, err := m.apiClient.GetBucketCORSRules( 671 context.Background(), 672 &apis.GetBucketCORSRulesRequest{ 673 Bucket: bucket, 674 }, 675 m.makeRequestOptions(), 676 ) 677 if err != nil { 678 return nil, err 679 } 680 rules := make([]CorsRule, 0, len(response.CORSRules)) 681 for _, rule := range response.CORSRules { 682 rules = append(rules, CorsRule{ 683 AllowedOrigin: rule.AllowedOrigin, 684 AllowedMethod: rule.AllowedMethod, 685 AllowedHeader: rule.AllowedHeader, 686 ExposedHeader: rule.ExposedHeader, 687 MaxAge: rule.MaxAge, 688 }) 689 } 690 return rules, nil 691 } 692 693 // BucketQuota 七牛存储空间的配额信息 694 type BucketQuota struct { 695 // 如果HTTP请求没有发送该参数或者发送的参数是0,表示不更改当前配置 696 // 如果是-1, 表示取消限额 697 // 一下两个参数都使用于这个逻辑 698 699 // 空间存储量配额信息 700 Size int64 701 702 // 空间文件数配置信息 703 Count int64 704 } 705 706 // SetBucketQuota 设置存储空间的配额限制 707 // 配额限制主要是两块, 空间存储量的限制和空间文件数限制 708 func (m *BucketManager) SetBucketQuota(bucket string, size, count int64) error { 709 _, err := m.apiClient.SetBucketQuota( 710 context.Background(), 711 &apis.SetBucketQuotaRequest{ 712 Bucket: bucket, 713 Size: size, 714 Count: count, 715 }, 716 m.makeRequestOptions(), 717 ) 718 return err 719 } 720 721 // GetBucketQuota 获取存储空间的配额信息 722 func (m *BucketManager) GetBucketQuota(bucket string) (quota BucketQuota, err error) { 723 response, err := m.apiClient.GetBucketQuota( 724 context.Background(), 725 &apis.GetBucketQuotaRequest{ 726 Bucket: bucket, 727 }, 728 m.makeRequestOptions(), 729 ) 730 if err != nil { 731 return BucketQuota{}, err 732 } 733 return BucketQuota{ 734 Size: response.Size, 735 Count: response.Count, 736 }, nil 737 } 738 739 // SetBucketAccessStyle 可以用来开启或关闭制定存储空间的原图保护 740 // mode - 1 ==> 开启原图保护 741 // mode - 0 ==> 关闭原图保护 742 func (m *BucketManager) SetBucketAccessStyle(bucket string, mode int) error { 743 _, err := m.apiClient.SetBucketAccessMode( 744 context.Background(), 745 &apis.SetBucketAccessModeRequest{ 746 Bucket: bucket, 747 Mode: int64(mode), 748 }, 749 m.makeRequestOptions(), 750 ) 751 return err 752 } 753 754 // TurnOffBucketProtected 开启指定存储空间的原图保护 755 func (m *BucketManager) TurnOnBucketProtected(bucket string) error { 756 return m.SetBucketAccessStyle(bucket, 1) 757 } 758 759 // TurnOffBucketProtected 关闭指定空间的原图保护 760 func (m *BucketManager) TurnOffBucketProtected(bucket string) error { 761 return m.SetBucketAccessStyle(bucket, 0) 762 } 763 764 // SetBucketMaxAge 设置指定存储空间的MaxAge响应头 765 // maxAge <= 0时,表示使用默认值31536000 766 func (m *BucketManager) SetBucketMaxAge(bucket string, maxAge int64) error { 767 _, err := m.apiClient.SetBucketMaxAge( 768 context.Background(), 769 &apis.SetBucketMaxAgeRequest{ 770 Bucket: bucket, 771 MaxAge: maxAge, 772 }, 773 m.makeRequestOptions(), 774 ) 775 return err 776 } 777 778 // SetBucketAccessMode 设置指定空间的私有属性 779 780 // mode - 1 表示设置空间为私有空间, 私有空间访问需要鉴权 781 // mode - 0 表示设置空间为公开空间 782 func (m *BucketManager) SetBucketAccessMode(bucket string, mode int) error { 783 _, err := m.apiClient.SetBucketPrivate( 784 context.Background(), 785 &apis.SetBucketPrivateRequest{ 786 Bucket: bucket, 787 IsPrivate: int64(mode), 788 }, 789 m.makeRequestOptions(), 790 ) 791 return err 792 } 793 794 // MakeBucketPublic 设置空间为公有空间 795 func (m *BucketManager) MakeBucketPublic(bucket string) error { 796 return m.SetBucketAccessMode(bucket, 0) 797 } 798 799 // MakeBucketPrivate 设置空间为私有空间 800 func (m *BucketManager) MakeBucketPrivate(bucket string) error { 801 return m.SetBucketAccessMode(bucket, 1) 802 } 803 804 // TurnOnIndexPage 设置默认首页 805 func (m *BucketManager) TurnOnIndexPage(bucket string) error { 806 return m.setIndexPage(bucket, 0) 807 } 808 809 // TurnOnIndexPage 关闭默认首页 810 func (m *BucketManager) TurnOffIndexPage(bucket string) error { 811 return m.setIndexPage(bucket, 1) 812 } 813 814 func (m *BucketManager) setIndexPage(bucket string, noIndexPage int) error { 815 _, err := m.apiClient.DisableBucketIndexPage( 816 context.Background(), 817 &apis.DisableBucketIndexPageRequest{ 818 Bucket: bucket, 819 NoIndexPage: int64(noIndexPage), 820 }, 821 m.makeRequestOptions(), 822 ) 823 return err 824 } 825 826 // BucketTagging 为 Bucket 设置标签 827 type BucketTagging struct { 828 Tags []BucketTag `json:"Tags"` 829 } 830 831 type BucketTag struct { 832 Key string `json:"Key"` 833 Value string `json:"Value"` 834 } 835 836 // SetTagging 设置 Bucket 标签 837 838 // SetTagging 该方法为覆盖所有 Bucket 上之前设置的标签,标签 Key 最大 64 字节,Value 最大 128 字节,均不能为空,且区分大小写 839 // Key 不能以 kodo 为前缀,Key 和 Value 的字符只能为:字母,数字,空格,+,-,=,.,_,:,/,@,不能支持中文 840 func (m *BucketManager) SetTagging(bucket string, tags map[string]string) error { 841 tagPairs := make(set_bucket_taggings.Tags, 0, len(tags)) 842 for k, v := range tags { 843 tagPairs = append(tagPairs, set_bucket_taggings.TagInfo{Key: k, Value: v}) 844 } 845 _, err := m.apiClient.SetBucketTaggings( 846 context.Background(), 847 &apis.SetBucketTaggingsRequest{ 848 Bucket: bucket, 849 Tags: tagPairs, 850 }, 851 m.makeRequestOptions(), 852 ) 853 return err 854 } 855 856 // ClearTagging 清空 Bucket 标签 857 func (m *BucketManager) ClearTagging(bucket string) error { 858 _, err := m.apiClient.DeleteBucketTaggings( 859 context.Background(), 860 &apis.DeleteBucketTaggingsRequest{ 861 BucketName: bucket, 862 }, 863 m.makeRequestOptions(), 864 ) 865 return err 866 } 867 868 // GetTagging 获取 Bucket 标签 869 func (m *BucketManager) GetTagging(bucket string) (map[string]string, error) { 870 response, err := m.apiClient.GetBucketTaggings( 871 context.Background(), 872 &apis.GetBucketTaggingsRequest{ 873 BucketName: bucket, 874 }, 875 m.makeRequestOptions(), 876 ) 877 if err != nil { 878 return nil, err 879 } 880 tags := make(map[string]string, len(response.Tags)) 881 for _, tag := range response.Tags { 882 tags[tag.Key] = tag.Value 883 } 884 return tags, nil 885 }