From 87f49432d0514158982bdccda4a15c6504c98701 Mon Sep 17 00:00:00 2001 From: mossju Date: Fri, 8 Oct 2021 11:47:26 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E5=86=85=E5=AE=B9=E5=AE=A1=E6=A0=B8?= =?UTF-8?q?=E5=85=AD=E6=9C=9F=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci.go | 182 ++++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 134 insertions(+), 48 deletions(-) diff --git a/ci.go b/ci.go index cba0ab6..055f784 100644 --- a/ci.go +++ b/ci.go @@ -101,6 +101,7 @@ func (s *CIService) ImageProcess(ctx context.Context, name string, opt *ImagePro return &res, resp, err } +// ImageRecognitionOptions is the option of ImageAuditing type ImageRecognitionOptions struct { CIProcess string `url:"ci-process,omitempty"` DetectType string `url:"detect-type,omitempty"` @@ -110,13 +111,21 @@ type ImageRecognitionOptions struct { BizType string `url:"biz-type,omitempty"` } +// ImageRecognitionResult is the result of ImageRecognition/ImageAuditing type ImageRecognitionResult struct { XMLName xml.Name `xml:"RecognitionResult"` + Text string `xml:"Text,omitempty"` + Label string `xml:"Label,omitempty"` + Result int `xml:"Result,omitempty"` + Score int `xml:"Score,omitempty"` + SubLabel string `xml:"SubLabel,omitempty"` PornInfo *RecognitionInfo `xml:"PornInfo,omitempty"` TerroristInfo *RecognitionInfo `xml:"TerroristInfo,omitempty"` PoliticsInfo *RecognitionInfo `xml:"PoliticsInfo,omitempty"` AdsInfo *RecognitionInfo `xml:"AdsInfo,omitempty"` } + +// RecognitionInfo is the result of auditing scene type RecognitionInfo struct { Code int `xml:"Code,omitempty"` Msg string `xml:"Msg,omitempty"` @@ -148,6 +157,7 @@ func (s *CIService) ImageRecognition(ctx context.Context, name string, DetectTyp resp, err := s.client.send(ctx, &sendOpt) return &res, resp, err } + // 图片审核 支持detect-url等全部参数 func (s *CIService) ImageAuditing(ctx context.Context, name string, opt *ImageRecognitionOptions) (*ImageRecognitionResult, *Response, error) { var res ImageRecognitionResult @@ -162,18 +172,25 @@ func (s *CIService) ImageAuditing(ctx context.Context, name string, opt *ImageRe return &res, resp, err } +// PutVideoAuditingJobOptions is the option of PutVideoAuditingJob type PutVideoAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` - InputObject string `xml:"Input>Object"` + InputObject string `xml:"Input>Object,omitempty"` + InputUrl string `xml:"Input>Url,omitempty"` Conf *VideoAuditingJobConf `xml:"Conf"` } + +// VideoAuditingJobConf is the config of PutVideoAuditingJobOptions type VideoAuditingJobConf struct { - DetectType string `xml:",omitempty"` - Snapshot *PutVideoAuditingJobSnapshot `xml:",omitempty"` - Callback string `xml:",omitempty"` - BizType string `xml:",omitempty"` - DetectContent int `xml:",omitempty"` + DetectType string `xml:",omitempty"` + Snapshot *PutVideoAuditingJobSnapshot `xml:",omitempty"` + Callback string `xml:",omitempty"` + CallbackVersion string `xml:",omitempty"` + BizType string `xml:",omitempty"` + DetectContent int `xml:",omitempty"` } + +// PutVideoAuditingJobSnapshot is the snapshot config of VideoAuditingJobConf type PutVideoAuditingJobSnapshot struct { Mode string `xml:",omitempty"` Count int `xml:",omitempty"` @@ -181,6 +198,7 @@ type PutVideoAuditingJobSnapshot struct { Start float32 `xml:",omitempty"` } +// PutVideoAuditingJobResult is the result of PutVideoAuditingJob type PutVideoAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail struct { @@ -205,41 +223,54 @@ func (s *CIService) PutVideoAuditingJob(ctx context.Context, opt *PutVideoAuditi return &res, resp, err } +// GetVideoAuditingJobResult is the result of GetVideoAuditingJob type GetVideoAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *AuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } + +// AuditingJobDetail is the detail of GetVideoAuditingJobResult type AuditingJobDetail struct { - Code string `xml:",omitempty"` - Message string `xml:",omitempty"` - JobId string `xml:",omitempty"` - State string `xml:",omitempty"` - CreationTime string `xml:",omitempty"` - Object string `xml:",omitempty"` - SnapshotCount string `xml:",omitempty"` - Result int `xml:",omitempty"` - PornInfo *RecognitionInfo `xml:",omitempty"` - TerrorismInfo *RecognitionInfo `xml:",omitempty"` - PoliticsInfo *RecognitionInfo `xml:",omitempty"` - AdsInfo *RecognitionInfo `xml:",omitempty"` - Snapshot *GetVideoAuditingJobSnapshot `xml:",omitempty"` - AudioSection *AudioSectionResult `xml:",omitempty"` -} + Code string `xml:",omitempty"` + Message string `xml:",omitempty"` + JobId string `xml:",omitempty"` + State string `xml:",omitempty"` + CreationTime string `xml:",omitempty"` + Object string `xml:",omitempty"` + Url string `xml:",omitempty"` + SnapshotCount string `xml:",omitempty"` + Label string `xml:",omitempty"` + Result int `xml:",omitempty"` + PornInfo *RecognitionInfo `xml:",omitempty"` + TerrorismInfo *RecognitionInfo `xml:",omitempty"` + PoliticsInfo *RecognitionInfo `xml:",omitempty"` + AdsInfo *RecognitionInfo `xml:",omitempty"` + Snapshot []GetVideoAuditingJobSnapshot `xml:",omitempty"` + AudioSection []AudioSectionResult `xml:",omitempty"` +} + +// GetVideoAuditingJobSnapshot is the snapshot result of AuditingJobDetail type GetVideoAuditingJobSnapshot struct { Url string `xml:",omitempty"` - SnapshotTime string `xml:",omitempty"` Text string `xml:",omitempty"` + SnapshotTime int `xml:",omitempty"` + Label string `xml:",omitempty"` + Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } + +// AudioSectionResult is the audio section result of AuditingJobDetail/AudioAuditingJobDetail type AudioSectionResult struct { Url string `xml:",omitempty"` Text string `xml:",omitempty"` OffsetTime int `xml:",omitempty"` Duration int `xml:",omitempty"` + Label string `xml:",omitempty"` + Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` @@ -259,18 +290,23 @@ func (s *CIService) GetVideoAuditingJob(ctx context.Context, jobid string) (*Get return &res, resp, err } +// PutAudioAuditingJobOptions is the option of PutAudioAuditingJob type PutAudioAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputObject string `xml:"Input>Object,omitempty"` InputUrl string `xml:"Input>Url,omitempty"` Conf *AudioAuditingJobConf `xml:"Conf"` } + +// AudioAuditingJobConf is the config of PutAudioAuditingJobOptions type AudioAuditingJobConf struct { DetectType string `xml:",omitempty"` Callback string `xml:",omitempty"` CallbackVersion string `xml:",omitempty"` BizType string `xml:",omitempty"` } + +// PutAudioAuditingJobResult is the result of PutAudioAuditingJob type PutAudioAuditingJobResult PutVideoAuditingJobResult // 音频审核-创建任务 https://cloud.tencent.com/document/product/460/53395 @@ -287,11 +323,14 @@ func (s *CIService) PutAudioAuditingJob(ctx context.Context, opt *PutAudioAuditi return &res, resp, err } +// GetAudioAuditingJobResult is the result of GetAudioAuditingJob type GetAudioAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *AudioAuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } + +// AudioAuditingJobDetail is the detail of GetAudioAuditingJobResult type AudioAuditingJobDetail struct { Code string `xml:",omitempty"` Message string `xml:",omitempty"` @@ -300,8 +339,9 @@ type AudioAuditingJobDetail struct { CreationTime string `xml:",omitempty"` Object string `xml:",omitempty"` Url string `xml:",omitempty"` - Result int `xml:",omitempty"` AudioText string `xml:",omitempty"` + Label string `xml:",omitempty"` + Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` @@ -322,17 +362,23 @@ func (s *CIService) GetAudioAuditingJob(ctx context.Context, jobid string) (*Get return &res, resp, err } +// PutTextAuditingJobOptions is the option of PutTextAuditingJob type PutTextAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputObject string `xml:"Input>Object,omitempty"` InputContent string `xml:"Input>Content,omitempty"` Conf *TextAuditingJobConf `xml:"Conf"` } + +// TextAuditingJobConf is the config of PutAudioAuditingJobOptions type TextAuditingJobConf struct { - DetectType string `xml:",omitempty"` - Callback string `xml:",omitempty"` - BizType string `xml:",omitempty"` + DetectType string `xml:",omitempty"` + Callback string `xml:",omitempty"` + CallbackVersion string `xml:",omitempty"` + BizType string `xml:",omitempty"` } + +// PutTextAuditingJobResult is the result of PutTextAuditingJob type PutTextAuditingJobResult GetTextAuditingJobResult // 文本审核-创建任务 https://cloud.tencent.com/document/product/436/56289 @@ -349,30 +395,40 @@ func (s *CIService) PutTextAuditingJob(ctx context.Context, opt *PutTextAuditing return &res, resp, err } +// GetTextAuditingJobResult is the result of GetTextAuditingJob type GetTextAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *TextAuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } + +// TextAuditingJobDetail is the detail of GetTextAuditingJobResult type TextAuditingJobDetail struct { - Code string `xml:",omitempty"` - Message string `xml:",omitempty"` - JobId string `xml:",omitempty"` - State string `xml:",omitempty"` - CreationTime string `xml:",omitempty"` - Object string `xml:",omitempty"` - SectionCount int `xml:",omitempty"` - Result int `xml:",omitempty"` - PornInfo *RecognitionInfo `xml:",omitempty"` - TerrorismInfo *RecognitionInfo `xml:",omitempty"` - PoliticsInfo *RecognitionInfo `xml:",omitempty"` - AdsInfo *RecognitionInfo `xml:",omitempty"` - IllegalInfo *RecognitionInfo `xml:",omitempty"` - AbuseInfo *RecognitionInfo `xml:",omitempty"` - Section *TextSectionResult `xml:",omitempty"` + Code string `xml:",omitempty"` + Message string `xml:",omitempty"` + JobId string `xml:",omitempty"` + State string `xml:",omitempty"` + CreationTime string `xml:",omitempty"` + Object string `xml:",omitempty"` + Url string `xml:",omitempty"` + Content string `xml:",omitempty"` + SectionCount int `xml:",omitempty"` + Label string `xml:",omitempty"` + Result int `xml:",omitempty"` + PornInfo *RecognitionInfo `xml:",omitempty"` + TerrorismInfo *RecognitionInfo `xml:",omitempty"` + PoliticsInfo *RecognitionInfo `xml:",omitempty"` + AdsInfo *RecognitionInfo `xml:",omitempty"` + IllegalInfo *RecognitionInfo `xml:",omitempty"` + AbuseInfo *RecognitionInfo `xml:",omitempty"` + Section []TextSectionResult `xml:",omitempty"` } + +// TextSectionResult is the section result of TextAuditingJobDetail type TextSectionResult struct { StartByte int `xml:",omitempty"` + Label string `xml:",omitempty"` + Result int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` @@ -394,13 +450,22 @@ func (s *CIService) GetTextAuditingJob(ctx context.Context, jobid string) (*GetT return &res, resp, err } +// PutDocumentAuditingJobOptions is the option of PutDocumentAuditingJob type PutDocumentAuditingJobOptions struct { XMLName xml.Name `xml:"Request"` InputUrl string `xml:"Input>Url,omitempty"` InputType string `xml:"Input>Type,omitempty"` Conf *DocumentAuditingJobConf `xml:"Conf"` } -type DocumentAuditingJobConf TextAuditingJobConf + +// DocumentAuditingJobConf is the config of PutDocumentAuditingJobOptions +type DocumentAuditingJobConf struct { + DetectType string `xml:",omitempty"` + Callback string `xml:",omitempty"` + BizType string `xml:",omitempty"` +} + +// PutDocumentAuditingJobResult is the result of PutDocumentAuditingJob type PutDocumentAuditingJobResult PutVideoAuditingJobResult // 文档审核-创建任务 https://cloud.tencent.com/document/product/436/59381 @@ -417,61 +482,82 @@ func (s *CIService) PutDocumentAuditingJob(ctx context.Context, opt *PutDocument return &res, resp, err } +// GetDocumentAuditingJobResult is the result of GetDocumentAuditingJob type GetDocumentAuditingJobResult struct { XMLName xml.Name `xml:"Response"` JobsDetail *DocumentAuditingJobDetail `xml:",omitempty"` NonExistJobIds string `xml:",omitempty"` } + +// DocumentAuditingJobDetail is the detail of GetDocumentAuditingJobResult type DocumentAuditingJobDetail struct { Code string `xml:",omitempty"` Message string `xml:",omitempty"` JobId string `xml:",omitempty"` State string `xml:",omitempty"` CreationTime string `xml:",omitempty"` - Suggestion int `xml:",omitempty"` + Object string `xml:",omitempty"` Url string `xml:",omitempty"` PageCount int `xml:",omitempty"` + Label string `xml:",omitempty"` + Suggestion int `xml:",omitempty"` Labels *DocumentResultInfo `xml:",omitempty"` PageSegment *DocumentPageSegmentInfo `xml:",omitempty"` } + +// DocumentResultInfo type DocumentResultInfo struct { PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } + +// DocumentPageSegmentInfo type DocumentPageSegmentInfo struct { Results []DocumentPageSegmentResultResult `xml:",omitempty"` } + +// DocumentPageSegmentResultResult type DocumentPageSegmentResultResult struct { Url string `xml:",omitempty"` Text string `xml:",omitempty"` PageNumber int `xml:",omitempty"` SheetNumber int `xml:",omitempty"` + Label string `xml:",omitempty"` + Suggestion int `xml:",omitempty"` PornInfo *RecognitionInfo `xml:",omitempty"` TerrorismInfo *RecognitionInfo `xml:",omitempty"` PoliticsInfo *RecognitionInfo `xml:",omitempty"` AdsInfo *RecognitionInfo `xml:",omitempty"` } + +// OcrResult type OcrResult struct { Text string `xml:"Text"` Keywords []string `xml:"Keywords"` Location *Location `xml:"Location,omitempty"` } + +// ObjectResult type ObjectResult struct { Name string `xml:"Name"` Location *Location `xml:"Location,omitempty"` } + +// LibResult type LibResult struct { ImageId string `xml:"ImageId"` Score uint32 `xml:"Score"` } + +// Location type Location struct { - X float64 `json:"X"` // 左上角横坐标 - Y float64 `json:"Y"` // 左上角纵坐标 - Width float64 `json:"Width"` // 宽度 - Height float64 `json:"Height"` // 高度 - Rotate float64 `json:"Rotate"` // 检测框的旋转角度 + X float64 `xml:"X,omitempty"` // 左上角横坐标 + Y float64 `xml:"Y,omitempty"` // 左上角纵坐标 + Width float64 `xml:"Width,omitempty"` // 宽度 + Height float64 `xml:"Height,omitempty"` // 高度 + Rotate float64 `xml:"Rotate,omitempty"` // 检测框的旋转角度 } // 文档审核-查询任务 https://cloud.tencent.com/document/product/436/59382 From b0532f56c62b132897e0a3b333cbc43f1f5393da Mon Sep 17 00:00:00 2001 From: jojoliang Date: Wed, 29 Sep 2021 17:32:17 +0800 Subject: [PATCH 2/4] add retry options --- auth.go | 1 + auth_test.go | 71 ++++++++++++++++++++++++++++++++++++++++ cos.go | 32 ++++++++++++++++-- example/object/get_with_retry.go | 59 +++++++++++++++++++++++++++++++++ object_test.go | 8 +++++ 5 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 example/object/get_with_retry.go diff --git a/auth.go b/auth.go index 6e06781..0a3e58f 100644 --- a/auth.go +++ b/auth.go @@ -65,6 +65,7 @@ var ciParameters = map[string]bool{ "imageview2/": true, } +// 非线程安全,只能在进程初始化(而不是Client初始化)时做设置 func SetNeedSignHeaders(key string, val bool) { NeedSignHeaders[key] = val } diff --git a/auth_test.go b/auth_test.go index e735e5b..ea4d79e 100644 --- a/auth_test.go +++ b/auth_test.go @@ -2,7 +2,11 @@ package cos import ( "context" + "fmt" "net/http" + "net/http/httptest" + "strconv" + "strings" "testing" "time" ) @@ -52,3 +56,70 @@ func TestAuthorizationTransport(t *testing.T) { req, _ := http.NewRequest("GET", client.BaseURL.BucketURL.String(), nil) client.doAPI(context.Background(), req, nil, true) } + +func TestCVMCredentialsTransport(t *testing.T) { + setup() + defer teardown() + uri := client.BaseURL.BucketURL.String() + ak := "test_ak" + sk := "test_sk" + token := "test_token" + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("x-cos-security-token") != token { + t.Errorf("CVMCredentialsTransport x-cos-security-token error, want:%v, return:%v\n", token, r.Header.Get("x-cos-security-token")) + } + auth := r.Header.Get("Authorization") + if auth == "" { + t.Error("CVMCredentialsTransport didn't add Authorization header") + } + field := strings.Split(auth, "&") + if len(field) != 7 { + t.Errorf("CVMCredentialsTransport Authorization header format error: %v\n", auth) + } + st_et := strings.Split(strings.Split(field[2], "=")[1], ";") + st, _ := strconv.ParseInt(st_et[0], 10, 64) + et, _ := strconv.ParseInt(st_et[1], 10, 64) + authTime := &AuthTime{ + SignStartTime: time.Unix(st, 0), + SignEndTime: time.Unix(et, 0), + KeyStartTime: time.Unix(st, 0), + KeyEndTime: time.Unix(et, 0), + } + host := strings.TrimLeft(uri, "http://") + req, _ := http.NewRequest("GET", uri, nil) + req.Header.Add("Host", host) + expect := newAuthorization(ak, sk, req, authTime) + if expect != auth { + t.Errorf("CVMCredentialsTransport Authorization error, want:%v, return:%v\n", expect, auth) + } + }) + + // CVM http server + cvm_mux := http.NewServeMux() + cvm_server := httptest.NewServer(cvm_mux) + defer cvm_server.Close() + // 将默认 CVM Host 修改成测试IP:PORT + defaultCVMMetaHost = strings.TrimLeft(cvm_server.URL, "http://") + + cvm_mux.HandleFunc("/"+defaultCVMCredURI, func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, "cvm_read_cos_only") + }) + cvm_mux.HandleFunc("/"+defaultCVMCredURI+"/cvm_read_cos_only", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, fmt.Sprintf(`{ + "TmpSecretId": "%s", + "TmpSecretKey": "%s", + "ExpiredTime": %v, + "Expiration": "now", + "Token": "%s", + "Code": "Success" + }`, ak, sk, time.Now().Unix()+3600, token)) + }) + + client.client.Transport = &CVMCredentialsTransport{} + req, _ := http.NewRequest("GET", client.BaseURL.BucketURL.String(), nil) + client.doAPI(context.Background(), req, nil, true) + + req, _ = http.NewRequest("GET", client.BaseURL.BucketURL.String(), nil) + client.doAPI(context.Background(), req, nil, true) +} diff --git a/cos.go b/cos.go index 1e411d5..c10fcef 100644 --- a/cos.go +++ b/cos.go @@ -13,6 +13,7 @@ import ( "reflect" "strings" "text/template" + "time" "strconv" @@ -72,9 +73,15 @@ func NewBucketURL(bucketName, region string, secure bool) *url.URL { return u } +type RetryOptions struct { + Count int + Interval time.Duration + StatusCode []int +} type Config struct { EnableCRC bool RequestBodyClose bool + RetryOpt RetryOptions } // Client is a client manages communication with the COS API. @@ -125,6 +132,10 @@ func NewClient(uri *BaseURL, httpClient *http.Client) *Client { Conf: &Config{ EnableCRC: true, RequestBodyClose: false, + RetryOpt: RetryOptions{ + Count: 3, + Interval: time.Duration(0), + }, }, } c.common.client = c @@ -309,14 +320,31 @@ func (c *Client) doRetry(ctx context.Context, opt *sendOptions) (resp *Response, return } } + count := 1 + if count < c.Conf.RetryOpt.Count { + count = c.Conf.RetryOpt.Count + } nr := 0 - for nr < 3 { + interval := c.Conf.RetryOpt.Interval + for nr < count { resp, err = c.send(ctx, opt) if err != nil { if resp != nil && resp.StatusCode <= 499 { - break + dobreak := true + for _, v := range c.Conf.RetryOpt.StatusCode { + if resp.StatusCode == v { + dobreak = false + break + } + } + if dobreak { + break + } } nr++ + if interval > 0 && nr < count { + time.Sleep(interval) + } continue } break diff --git a/example/object/get_with_retry.go b/example/object/get_with_retry.go new file mode 100644 index 0000000..f9c7cc0 --- /dev/null +++ b/example/object/get_with_retry.go @@ -0,0 +1,59 @@ +package main + +import ( + "context" + "fmt" + "net/url" + + "net/http" + "os" + "time" + + "github.com/agin719/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +func log_status(err error) { + if err == nil { + return + } + if cos.IsNotFoundError(err) { + // WARN + fmt.Println("WARN: Resource is not existed") + } else if e, ok := cos.IsCOSError(err); ok { + fmt.Printf("ERROR: Code: %v\n", e.Code) + fmt.Printf("ERROR: Message: %v\n", e.Message) + fmt.Printf("ERROR: Resource: %v\n", e.Resource) + fmt.Printf("ERROR: RequestId: %v\n", e.RequestID) + // ERROR + } else { + fmt.Printf("ERROR: %v\n", err) + // ERROR + } +} + +func main() { + u, _ := url.Parse("https://test-1259654469.cos.ap-guangzhou.myqcloud.com") + b := &cos.BaseURL{BucketURL: u} + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: os.Getenv("COS_SECRETID"), + SecretKey: os.Getenv("COS_SECRETKEY"), + Transport: &debug.DebugRequestTransport{ + RequestHeader: true, + // Notice when put a large file and set need the request body, might happend out of memory error. + RequestBody: false, + ResponseHeader: true, + ResponseBody: false, + }, + }, + }) + // Get 请求配置重试 + c.Conf.RetryOpt.Count = 3 // 错误重试次数,默认重试3次 + c.Conf.RetryOpt.Interval = time.Millisecond // 错误重试间隔时间,默认0 + c.Conf.RetryOpt.StatusCode = []int{200} // 默认5xx都会重试,该参数配置其余需要重试的响应码 + + name := "exampleobject" + _, err := c.Object.Get(context.Background(), name, nil) + log_status(err) +} diff --git a/object_test.go b/object_test.go index bfc7c4a..02d6299 100644 --- a/object_test.go +++ b/object_test.go @@ -121,6 +121,7 @@ func TestObjectService_GetRetry(t *testing.T) { ResponseHeaderTimeout: 1 * time.Second, }, }) + client.Conf.RetryOpt.StatusCode = []int{499} name := "test/hello.txt" contentLength := 1024 * 1024 * 10 data := make([]byte, contentLength) @@ -132,6 +133,10 @@ func TestObjectService_GetRetry(t *testing.T) { } index++ if index%3 != 0 { + if index > 6 { + w.WriteHeader(499) + return + } time.Sleep(time.Second * 2) } testFormValues(t, r, vs) @@ -163,6 +168,9 @@ func TestObjectService_GetRetry(t *testing.T) { t.Errorf("Object.Get Failed") } } + if index != 9 { + t.Errorf("retry time error, retry count: %v\n", index) + } } func TestObjectService_GetPresignedURL(t *testing.T) { From 6372b2ef3cbc66be72e77e222e3d49c0d3ced254 Mon Sep 17 00:00:00 2001 From: jojoliang Date: Wed, 29 Sep 2021 17:39:34 +0800 Subject: [PATCH 3/4] update demo --- example/object/get_with_retry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/object/get_with_retry.go b/example/object/get_with_retry.go index f9c7cc0..cb0138b 100644 --- a/example/object/get_with_retry.go +++ b/example/object/get_with_retry.go @@ -9,7 +9,7 @@ import ( "os" "time" - "github.com/agin719/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5" "github.com/tencentyun/cos-go-sdk-v5/debug" ) From e9c0af3ad1eb0582e9517c4f80af922e0e181469 Mon Sep 17 00:00:00 2001 From: jojoliang Date: Wed, 29 Sep 2021 17:41:00 +0800 Subject: [PATCH 4/4] update demo --- example/object/get_with_retry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/object/get_with_retry.go b/example/object/get_with_retry.go index cb0138b..48a240c 100644 --- a/example/object/get_with_retry.go +++ b/example/object/get_with_retry.go @@ -51,7 +51,7 @@ func main() { // Get 请求配置重试 c.Conf.RetryOpt.Count = 3 // 错误重试次数,默认重试3次 c.Conf.RetryOpt.Interval = time.Millisecond // 错误重试间隔时间,默认0 - c.Conf.RetryOpt.StatusCode = []int{200} // 默认5xx都会重试,该参数配置其余需要重试的响应码 + c.Conf.RetryOpt.StatusCode = []int{} // 默认5xx都会重试,该参数配置其余需要重试的响应码 name := "exampleobject" _, err := c.Object.Get(context.Background(), name, nil)