Browse Source

add ci guetzli && test

master
jojoliang 4 years ago
parent
commit
caee386405
  1. 7
      batch.go
  2. 9
      bucket_origin.go
  3. 180
      bucket_origin_test.go
  4. 121
      bucket_policy_test.go
  5. 40
      ci.go
  6. 497
      ci_test.go
  7. 33
      error_test.go
  8. 58
      example/CI/compression/ci_compression.go
  9. 68
      example/CI/compression/guetzli.go
  10. 173
      object_test.go

7
batch.go

@ -113,13 +113,6 @@ type BatchCreateJobResult struct {
JobId string `xml:"JobId,omitempty"`
}
func processETag(opt *BatchCreateJobOptions) *BatchCreateJobOptions {
if opt != nil && opt.Manifest != nil && opt.Manifest.Location != nil {
opt.Manifest.Location.ETag = "<ETag>" + opt.Manifest.Location.ETag + "</ETag>"
}
return opt
}
func (s *BatchService) CreateJob(ctx context.Context, opt *BatchCreateJobOptions, headers *BatchRequestHeaders) (*BatchCreateJobResult, *Response, error) {
var res BatchCreateJobResult
sendOpt := sendOptions{

9
bucket_origin.go

@ -12,10 +12,11 @@ type BucketPutOriginOptions struct {
}
type BucketOriginRule struct {
OriginType string `xml:"OriginType"`
OriginCondition *BucketOriginCondition `xml:"OriginCondition"`
OriginParameter *BucketOriginParameter `xml:"OriginParameter"`
OriginInfo *BucketOriginInfo `xml:"OriginInfo"`
RulePriority int `xml:"RulePriority,omitempty"`
OriginType string `xml:"OriginType,omitempty"`
OriginCondition *BucketOriginCondition `xml:"OriginCondition,omitempty"`
OriginParameter *BucketOriginParameter `xml:"OriginParameter,omitempty"`
OriginInfo *BucketOriginInfo `xml:"OriginInfo,omitempty"`
}
type BucketOriginCondition struct {

180
bucket_origin_test.go

@ -0,0 +1,180 @@
package cos
import (
"context"
"encoding/xml"
"fmt"
"net/http"
"reflect"
"testing"
)
func TestBucketService_GetOrigin(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
vs := values{
"origin": "",
}
testFormValues(t, r, vs)
fmt.Fprint(w, `<OriginConfiguration>
<OriginRule>
<RulePriority>1</RulePriority>
<OriginType>Mirror</OriginType>
<OriginCondition>
<HTTPStatusCode>404</HTTPStatusCode>
<Prefix></Prefix>
</OriginCondition>
<OriginParameter>
<Protocol>HTTP</Protocol>
<FollowQueryString>true</FollowQueryString>
<HttpHeader>
<NewHttpHeaders>
<Header>
<Key>x-cos</Key>
<Value>exampleHeader</Value>
</Header>
</NewHttpHeaders>
<FollowHttpHeaders>
<Header>
<Key>exampleHeaderKey</Key>
</Header>
</FollowHttpHeaders>
</HttpHeader>
<FollowRedirection>true</FollowRedirection>
<HttpRedirectCode>302</HttpRedirectCode>
</OriginParameter>
<OriginInfo>
<HostInfo>
<HostName>examplebucket-1250000000.cos.ap-shanghai.myqcloud.com</HostName>
</HostInfo>
</OriginInfo>
</OriginRule>
</OriginConfiguration>
`)
})
res, _, err := client.Bucket.GetOrigin(context.Background())
if err != nil {
t.Fatalf("Bucket.GetOrigin returned error %v", err)
}
want := &BucketGetOriginResult{
XMLName: xml.Name{Local: "OriginConfiguration"},
Rule: []BucketOriginRule{
{
OriginType: "Mirror",
RulePriority: 1,
OriginCondition: &BucketOriginCondition{
HTTPStatusCode: "404",
},
OriginParameter: &BucketOriginParameter{
Protocol: "HTTP",
FollowQueryString: true,
HttpHeader: &BucketOriginHttpHeader{
FollowHttpHeaders: []OriginHttpHeader{
{
Key: "exampleHeaderKey",
},
},
NewHttpHeaders: []OriginHttpHeader{
{
Key: "x-cos",
Value: "exampleHeader",
},
},
},
FollowRedirection: true,
HttpRedirectCode: "302",
},
OriginInfo: &BucketOriginInfo{
HostInfo: "examplebucket-1250000000.cos.ap-shanghai.myqcloud.com",
},
},
},
}
if !reflect.DeepEqual(res, want) {
t.Errorf("Bucket.GetOrigin returned %+v, want %+v", res, want)
}
}
func TestBucketService_PutOrigin(t *testing.T) {
setup()
defer teardown()
opt := &BucketPutOriginOptions{
XMLName: xml.Name{Local: "OriginConfiguration"},
Rule: []BucketOriginRule{
{
OriginType: "Mirror",
RulePriority: 1,
OriginCondition: &BucketOriginCondition{
HTTPStatusCode: "404",
},
OriginParameter: &BucketOriginParameter{
Protocol: "HTTP",
FollowQueryString: true,
HttpHeader: &BucketOriginHttpHeader{
FollowHttpHeaders: []OriginHttpHeader{
{
Key: "exampleHeaderKey",
},
},
NewHttpHeaders: []OriginHttpHeader{
{
Key: "x-cos",
Value: "exampleHeader",
},
},
},
FollowRedirection: true,
HttpRedirectCode: "302",
},
OriginInfo: &BucketOriginInfo{
HostInfo: "examplebucket-1250000000.cos.ap-shanghai.myqcloud.com",
},
},
},
}
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
vs := values{
"origin": "",
}
testFormValues(t, r, vs)
body := new(BucketPutOriginOptions)
xml.NewDecoder(r.Body).Decode(body)
want := opt
want.XMLName = xml.Name{Local: "OriginConfiguration"}
if !reflect.DeepEqual(body, want) {
t.Errorf("Bucket.PutOrigin request\n body: %+v\n, want %+v\n", body, want)
}
})
_, err := client.Bucket.PutOrigin(context.Background(), opt)
if err != nil {
t.Fatalf("Bucket.PutOrigin returned error: %v", err)
}
}
func TestBucketService_DeleteOrigin(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodDelete)
vs := values{
"origin": "",
}
testFormValues(t, r, vs)
w.WriteHeader(http.StatusNoContent)
})
_, err := client.Bucket.DeleteOrigin(context.Background())
if err != nil {
t.Fatalf("Bucket.DeleteOrigin returned error: %v", err)
}
}

121
bucket_policy_test.go

@ -0,0 +1,121 @@
package cos
import (
"context"
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
)
func TestBucketService_GetPolicy(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
vs := values{
"policy": "",
}
testFormValues(t, r, vs)
fmt.Fprint(w, `{
"Statement": [
{
"Principal": {
"qcs": [
"qcs::cam::uin/100000000001:uin/100000000011"
]
},
"Effect": "allow",
"Action": [
"name/cos:GetBucket"
],
"Resource": [
"qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/*"
]
}
],
"version": "2.0"
}`)
})
res, _, err := client.Bucket.GetPolicy(context.Background())
if err != nil {
t.Fatalf("Bucket.GetPolicy returned error %v", err)
}
want := &BucketGetPolicyResult{
Statement: []BucketStatement{
{
Principal: map[string][]string{
"qcs": []string{"qcs::cam::uin/100000000001:uin/100000000011"},
},
Effect: "allow",
Action: []string{"name/cos:GetBucket"},
Resource: []string{"qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/*"},
},
},
Version: "2.0",
}
if !reflect.DeepEqual(res, want) {
t.Errorf("Bucket.GetPolicy returned %+v, want %+v", res, want)
}
}
func TestBucketService_PutPolicy(t *testing.T) {
setup()
defer teardown()
opt := &BucketPutPolicyOptions{
Statement: []BucketStatement{
{
Principal: map[string][]string{
"qcs": []string{"qcs::cam::uin/100000000001:uin/100000000011"},
},
Effect: "allow",
Action: []string{"name/cos:GetBucket"},
Resource: []string{"qcs::cos:ap-guangzhou:uid/1250000000:examplebucket-1250000000/*"},
},
},
Version: "2.0",
}
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
vs := values{
"policy": "",
}
testFormValues(t, r, vs)
body := new(BucketPutPolicyOptions)
json.NewDecoder(r.Body).Decode(body)
want := opt
if !reflect.DeepEqual(body, want) {
t.Errorf("Bucket.PutPolicy request\n body: %+v\n, want %+v\n", body, want)
}
})
_, err := client.Bucket.PutPolicy(context.Background(), opt)
if err != nil {
t.Fatalf("Bucket.PutPolicy returned error: %v", err)
}
}
func TestBucketService_DeletePolicy(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodDelete)
vs := values{
"policy": "",
}
testFormValues(t, r, vs)
w.WriteHeader(http.StatusNoContent)
})
_, err := client.Bucket.DeletePolicy(context.Background())
if err != nil {
t.Fatalf("Bucket.DeletePolicy returned error: %v", err)
}
}

40
ci.go

@ -446,3 +446,43 @@ func (s *CIService) GenerateQRcodeToFile(ctx context.Context, filePath string, o
return res, resp, err
}
// 开通 Guetzli 压缩 https://cloud.tencent.com/document/product/460/30112
func (s *CIService) PutGuetzli(ctx context.Context) (*Response, error) {
sendOpt := &sendOptions{
baseURL: s.client.BaseURL.CIURL,
uri: "/?guetzli",
method: http.MethodPut,
}
resp, err := s.client.send(ctx, sendOpt)
return resp, err
}
type GetGuetzliResult struct {
XMLName xml.Name `xml:"GuetzliStatus"`
GuetzliStatus string `xml:",chardata"`
}
// 查询 Guetzli 状态 https://cloud.tencent.com/document/product/460/30111
func (s *CIService) GetGuetzli(ctx context.Context) (*GetGuetzliResult, *Response, error) {
var res GetGuetzliResult
sendOpt := &sendOptions{
baseURL: s.client.BaseURL.CIURL,
uri: "/?guetzli",
method: http.MethodGet,
result: &res,
}
resp, err := s.client.send(ctx, sendOpt)
return &res, resp, err
}
// 关闭 Guetzli 压缩 https://cloud.tencent.com/document/product/460/30113
func (s *CIService) DeleteGuetzli(ctx context.Context) (*Response, error) {
sendOpt := &sendOptions{
baseURL: s.client.BaseURL.CIURL,
uri: "/?guetzli",
method: http.MethodDelete,
}
resp, err := s.client.send(ctx, sendOpt)
return resp, err
}

497
ci_test.go

@ -0,0 +1,497 @@
package cos
import (
"bytes"
"context"
"crypto/rand"
"encoding/json"
"encoding/xml"
"fmt"
"hash/crc64"
"io/ioutil"
"net/http"
"os"
"reflect"
"strconv"
"testing"
"time"
)
func TestCIService_EncodePicOperations(t *testing.T) {
opt := &PicOperations{
IsPicInfo: 1,
Rules: []PicOperationsRules{
{
FileId: "example.jpg",
Rule: "imageView2/format/png",
},
},
}
res := EncodePicOperations(opt)
jsonStr := `{"is_pic_info":1,"rules":[{"fileid":"example.jpg","rule":"imageView2/format/png"}]}`
if jsonStr != res {
t.Fatalf("EncodePicOperations Failed, returned:%v, want:%v", res, jsonStr)
}
}
func TestCIService_ImageProcess(t *testing.T) {
setup()
defer teardown()
name := "test.jpg"
opt := &ImageProcessOptions{
IsPicInfo: 1,
Rules: []PicOperationsRules{
{
FileId: "format.jpg",
Rule: "imageView2/format/png",
},
},
}
mux.HandleFunc("/test.jpg", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
vs := values{
"image_process": "",
}
testFormValues(t, r, vs)
header := r.Header.Get("Pic-Operations")
body := new(ImageProcessOptions)
err := json.Unmarshal([]byte(header), body)
want := opt
if err != nil {
t.Errorf("CI.ImageProcess Failed: %v", err)
}
if !reflect.DeepEqual(want, body) {
t.Errorf("CI.ImageProcess Failed, wanted:%v, body:%v", want, body)
}
fmt.Fprint(w, `<UploadResult>
<OriginalInfo>
<Key>test.jpg</Key>
<Location>example-1250000000.cos.ap-guangzhou.myqcloud.com/test.jpg</Location>
<ETag>&quot;8894dbe5e3ebfaf761e39b9d619c28f3327b8d85&quot;</ETag>
<ImageInfo>
<Format>PNG</Format>
<Width>103</Width>
<Height>99</Height>
<Quality>100</Quality>
<Ave>0xa08162</Ave>
<Orientation>0</Orientation>
</ImageInfo>
</OriginalInfo>
<ProcessResults>
<Object>
<Key>format.jpg</Key>
<Location>example-1250000000.cos.ap-guangzhou.myqcloud.com/format.jpg</Location>
<Format>PNG</Format>
<Width>103</Width>
<Height>99</Height>
<Size>21351</Size>
<Quality>100</Quality>
<ETag>&quot;8894dbe5e3ebfaf761e39b9d619c28f3327b8d85&quot;</ETag>
</Object>
</ProcessResults>
</UploadResult>`)
})
want := &ImageProcessResult{
XMLName: xml.Name{Local: "UploadResult"},
OriginalInfo: &PicOriginalInfo{
Key: "test.jpg",
Location: "example-1250000000.cos.ap-guangzhou.myqcloud.com/test.jpg",
ETag: "\"8894dbe5e3ebfaf761e39b9d619c28f3327b8d85\"",
ImageInfo: &PicImageInfo{
Format: "PNG",
Width: 103,
Height: 99,
Quality: 100,
Ave: "0xa08162",
Orientation: 0,
},
},
ProcessResults: &PicProcessObject{
Key: "format.jpg",
Location: "example-1250000000.cos.ap-guangzhou.myqcloud.com/format.jpg",
Format: "PNG",
Width: 103,
Height: 99,
Size: 21351,
Quality: 100,
ETag: "\"8894dbe5e3ebfaf761e39b9d619c28f3327b8d85\"",
},
}
res, _, err := client.CI.ImageProcess(context.Background(), name, opt)
if err != nil {
t.Fatalf("CI.ImageProcess returned error: %v", err)
}
if !reflect.DeepEqual(res, want) {
t.Errorf("CI.ImageProcess failed, return:%v, want:%v", res, want)
}
}
func TestCIService_ImageRecognition(t *testing.T) {
setup()
defer teardown()
name := "test.jpg"
detectType := "porn,terrorist,politics"
mux.HandleFunc("/test.jpg", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
vs := values{
"ci-process": "sensitive-content-recognition",
"detect-type": "porn,terrorist,politics",
}
testFormValues(t, r, vs)
fmt.Fprint(w, `<RecognitionResult>
<PornInfo>
<Code>0</Code>
<Msg>OK</Msg>
<HitFlag>0</HitFlag>
<Score>0</Score>
<Label/>
</PornInfo>
<TerroristInfo>
<Code>0</Code>
<Msg>OK</Msg>
<HitFlag>0</HitFlag>
<Score>0</Score>
<Label/>
</TerroristInfo>
<PoliticsInfo>
<Code>0</Code>
<Msg>OK</Msg>
<HitFlag>0</HitFlag>
<Score>0</Score>
<Label/>
</PoliticsInfo>
</RecognitionResult>`)
})
want := &ImageRecognitionResult{
XMLName: xml.Name{Local: "RecognitionResult"},
PornInfo: &RecognitionInfo{
Code: 0,
Msg: "OK",
HitFlag: 0,
Score: 0,
},
TerroristInfo: &RecognitionInfo{
Code: 0,
Msg: "OK",
HitFlag: 0,
Score: 0,
},
PoliticsInfo: &RecognitionInfo{
Code: 0,
Msg: "OK",
HitFlag: 0,
Score: 0,
},
}
res, _, err := client.CI.ImageRecognition(context.Background(), name, detectType)
if err != nil {
t.Fatalf("CI.ImageRecognitionreturned error: %v", err)
}
if !reflect.DeepEqual(res, want) {
t.Errorf("CI.ImageRecognition failed, return:%v, want:%v", res, want)
}
}
func TestCIService_Put(t *testing.T) {
setup()
defer teardown()
name := "test.jpg"
data := make([]byte, 1024*1024*3)
rand.Read(data)
pic := &ImageProcessOptions{
IsPicInfo: 1,
Rules: []PicOperationsRules{
{
FileId: "format.jpg",
Rule: "imageView2/format/png",
},
},
}
mux.HandleFunc("/test.jpg", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
header := r.Header.Get("Pic-Operations")
body := new(ImageProcessOptions)
err := json.Unmarshal([]byte(header), body)
want := pic
if err != nil {
t.Errorf("CI.Put Failed: %v", err)
}
if !reflect.DeepEqual(want, body) {
t.Errorf("CI.Put Failed, wanted:%v, body:%v", want, body)
}
tb := crc64.MakeTable(crc64.ECMA)
ht := crc64.New(tb)
tr := TeeReader(r.Body, ht, 0, nil)
bs, err := ioutil.ReadAll(tr)
if err != nil {
t.Errorf("CI.Put ReadAll Failed: %v", err)
}
if bytes.Compare(bs, data) != 0 {
t.Errorf("CI.Put Failed, data isn't consistent")
}
crc := tr.Crc64()
w.Header().Add("x-cos-hash-crc64ecma", strconv.FormatUint(crc, 10))
fmt.Fprint(w, `<UploadResult>
<OriginalInfo>
<Key>test.jpg</Key>
<Location>example-1250000000.cos.ap-guangzhou.myqcloud.com/test.jpg</Location>
<ETag>&quot;8894dbe5e3ebfaf761e39b9d619c28f3327b8d85&quot;</ETag>
<ImageInfo>
<Format>PNG</Format>
<Width>103</Width>
<Height>99</Height>
<Quality>100</Quality>
<Ave>0xa08162</Ave>
<Orientation>0</Orientation>
</ImageInfo>
</OriginalInfo>
<ProcessResults>
<Object>
<Key>format.jpg</Key>
<Location>example-1250000000.cos.ap-guangzhou.myqcloud.com/format.jpg</Location>
<Format>PNG</Format>
<Width>103</Width>
<Height>99</Height>
<Size>21351</Size>
<Quality>100</Quality>
<ETag>&quot;8894dbe5e3ebfaf761e39b9d619c28f3327b8d85&quot;</ETag>
</Object>
</ProcessResults>
</UploadResult>`)
})
want := &ImageProcessResult{
XMLName: xml.Name{Local: "UploadResult"},
OriginalInfo: &PicOriginalInfo{
Key: "test.jpg",
Location: "example-1250000000.cos.ap-guangzhou.myqcloud.com/test.jpg",
ETag: "\"8894dbe5e3ebfaf761e39b9d619c28f3327b8d85\"",
ImageInfo: &PicImageInfo{
Format: "PNG",
Width: 103,
Height: 99,
Quality: 100,
Ave: "0xa08162",
Orientation: 0,
},
},
ProcessResults: &PicProcessObject{
Key: "format.jpg",
Location: "example-1250000000.cos.ap-guangzhou.myqcloud.com/format.jpg",
Format: "PNG",
Width: 103,
Height: 99,
Size: 21351,
Quality: 100,
ETag: "\"8894dbe5e3ebfaf761e39b9d619c28f3327b8d85\"",
},
}
f := bytes.NewReader(data)
opt := &ObjectPutOptions{
nil,
&ObjectPutHeaderOptions{
XOptionHeader: &http.Header{},
},
}
opt.XOptionHeader.Add("Pic-Operations", EncodePicOperations(pic))
res, _, err := client.CI.Put(context.Background(), name, f, opt)
if err != nil {
t.Fatalf("CI.Put returned error: %v", err)
}
if !reflect.DeepEqual(res, want) {
t.Errorf("CI.ImageProcess failed, return:%v, want:%v", res, want)
}
}
func TestCIService_PutFromFile(t *testing.T) {
setup()
defer teardown()
name := "test.jpg"
filePath := "test.file" + time.Now().Format(time.RFC3339)
newfile, err := os.Create(filePath)
if err != nil {
t.Fatalf("creat tmp file failed")
}
defer os.Remove(filePath)
data := make([]byte, 1024*1024*3)
rand.Read(data)
newfile.Write(data)
newfile.Close()
pic := &ImageProcessOptions{
IsPicInfo: 1,
Rules: []PicOperationsRules{
{
FileId: "format.jpg",
Rule: "imageView2/format/png",
},
},
}
mux.HandleFunc("/test.jpg", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
header := r.Header.Get("Pic-Operations")
body := new(ImageProcessOptions)
err := json.Unmarshal([]byte(header), body)
want := pic
if err != nil {
t.Errorf("CI.Put Failed: %v", err)
}
if !reflect.DeepEqual(want, body) {
t.Errorf("CI.Put Failed, wanted:%v, body:%v", want, body)
}
tb := crc64.MakeTable(crc64.ECMA)
ht := crc64.New(tb)
tr := TeeReader(r.Body, ht, 0, nil)
bs, err := ioutil.ReadAll(tr)
if err != nil {
t.Errorf("CI.Put ReadAll Failed: %v", err)
}
if bytes.Compare(bs, data) != 0 {
t.Errorf("CI.Put Failed, data isn't consistent")
}
crc := tr.Crc64()
w.Header().Add("x-cos-hash-crc64ecma", strconv.FormatUint(crc, 10))
fmt.Fprint(w, `<UploadResult>
<OriginalInfo>
<Key>test.jpg</Key>
<Location>example-1250000000.cos.ap-guangzhou.myqcloud.com/test.jpg</Location>
<ETag>&quot;8894dbe5e3ebfaf761e39b9d619c28f3327b8d85&quot;</ETag>
<ImageInfo>
<Format>PNG</Format>
<Width>103</Width>
<Height>99</Height>
<Quality>100</Quality>
<Ave>0xa08162</Ave>
<Orientation>0</Orientation>
</ImageInfo>
</OriginalInfo>
<ProcessResults>
<Object>
<Key>format.jpg</Key>
<Location>example-1250000000.cos.ap-guangzhou.myqcloud.com/format.jpg</Location>
<Format>PNG</Format>
<Width>103</Width>
<Height>99</Height>
<Size>21351</Size>
<Quality>100</Quality>
<ETag>&quot;8894dbe5e3ebfaf761e39b9d619c28f3327b8d85&quot;</ETag>
</Object>
</ProcessResults>
</UploadResult>`)
})
want := &ImageProcessResult{
XMLName: xml.Name{Local: "UploadResult"},
OriginalInfo: &PicOriginalInfo{
Key: "test.jpg",
Location: "example-1250000000.cos.ap-guangzhou.myqcloud.com/test.jpg",
ETag: "\"8894dbe5e3ebfaf761e39b9d619c28f3327b8d85\"",
ImageInfo: &PicImageInfo{
Format: "PNG",
Width: 103,
Height: 99,
Quality: 100,
Ave: "0xa08162",
Orientation: 0,
},
},
ProcessResults: &PicProcessObject{
Key: "format.jpg",
Location: "example-1250000000.cos.ap-guangzhou.myqcloud.com/format.jpg",
Format: "PNG",
Width: 103,
Height: 99,
Size: 21351,
Quality: 100,
ETag: "\"8894dbe5e3ebfaf761e39b9d619c28f3327b8d85\"",
},
}
opt := &ObjectPutOptions{
nil,
&ObjectPutHeaderOptions{
XOptionHeader: &http.Header{},
},
}
opt.XOptionHeader.Add("Pic-Operations", EncodePicOperations(pic))
res, _, err := client.CI.PutFromFile(context.Background(), name, filePath, opt)
if err != nil {
t.Fatalf("CI.Put returned error: %v", err)
}
if !reflect.DeepEqual(res, want) {
t.Errorf("CI.ImageProcess failed, return:%v, want:%v", res, want)
}
}
func TestBucketService_GetGuetzli(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
vs := values{
"guetzli": "",
}
testFormValues(t, r, vs)
fmt.Fprint(w, `<GuetzliStatus>on</GuetzliStatus>`)
})
res, _, err := client.CI.GetGuetzli(context.Background())
if err != nil {
t.Fatalf("CI.GetGuetzli returned error %v", err)
}
want := &GetGuetzliResult{
XMLName: xml.Name{Local: "GuetzliStatus"},
GuetzliStatus: "on",
}
if !reflect.DeepEqual(res, want) {
t.Errorf("CI.GetGuetzli %+v, want %+v", res, want)
}
}
func TestBucketService_PutGuetzli(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PUT")
vs := values{
"guetzli": "",
}
testFormValues(t, r, vs)
})
_, err := client.CI.PutGuetzli(context.Background())
if err != nil {
t.Fatalf("CI.PutGuetzli returned error: %v", err)
}
}
func TestBucketService_DeleteGuetzli(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "DELETE")
vs := values{
"guetzli": "",
}
testFormValues(t, r, vs)
w.WriteHeader(http.StatusNoContent)
})
_, err := client.CI.DeleteGuetzli(context.Background())
if err != nil {
t.Fatalf("CI.PutGuetzli returned error: %v", err)
}
}

33
error_test.go

@ -87,3 +87,36 @@ func Test_checkResponse_with_error(t *testing.T) {
}
}
func Test_IsNotFoundError(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/test_404", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprint(w, `<?xml version='1.0' encoding='utf-8' ?>
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Resource>examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com/test_404</Resource>
<RequestId>NjA3OGY4NGFfNjJkMmMwYl8***</RequestId>
<TraceId>OGVmYzZiMmQzYjA2OWNh***</TraceId>
</Error>`)
})
req, _ := http.NewRequest("GET", client.BaseURL.ServiceURL.String()+"/test_404", nil)
resp, _ := client.client.Do(req)
err := checkResponse(resp)
e, ok := IsCOSError(err)
if !ok {
t.Errorf("IsCOSError Return Failed")
}
ok = IsNotFoundError(e)
if !ok {
t.Errorf("IsNotFoundError Return Failed")
}
if e.Code != "NoSuchKey" {
t.Errorf("Expected NoSuchKey error, got %+v", e.Code)
}
}

58
example/CI/compression/ci_compression.go

@ -0,0 +1,58 @@
package main
import (
"context"
"fmt"
"net/http"
"net/url"
"os"
"github.com/tencentyun/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,
},
},
})
name := "test.png"
filepath := "test1.jpg"
_, err := c.CI.GetToFile(context.Background(), name, filepath, "imageMogr2/format/tpg", nil)
log_status(err)
filepath = "test2.jpg"
_, err = c.CI.GetToFile(context.Background(), name, filepath, "imageMogr2/format/heif", nil)
log_status(err)
}

68
example/CI/compression/guetzli.go

@ -0,0 +1,68 @@
package main
import (
"context"
"fmt"
"net/http"
"net/url"
"os"
"time"
"github.com/tencentyun/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")
cu, _ := url.Parse("http://test-1259654469.pic.ap-guangzhou.myqcloud.com")
b := &cos.BaseURL{BucketURL: u, CIURL: cu}
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: true,
},
},
})
_, err := c.CI.PutGuetzli(context.Background())
log_status(err)
res, _, err := c.CI.GetGuetzli(context.Background())
log_status(err)
if res != nil && res.GuetzliStatus != "on" {
fmt.Printf("Error Status: %v\n", res.GuetzliStatus)
}
time.Sleep(time.Second * 3)
_, err = c.CI.DeleteGuetzli(context.Background())
log_status(err)
res, _, err = c.CI.GetGuetzli(context.Background())
log_status(err)
if res != nil && res.GuetzliStatus != "off" {
fmt.Printf("Error Status: %v\n", res.GuetzliStatus)
}
}

173
object_test.go

@ -25,6 +25,8 @@ func TestObjectService_Get(t *testing.T) {
setup()
defer teardown()
name := "test/hello.txt"
contentLength := 1024 * 1024 * 10
data := make([]byte, contentLength)
mux.HandleFunc("/test/hello.txt", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
@ -32,27 +34,70 @@ func TestObjectService_Get(t *testing.T) {
"response-content-type": "text/html",
}
testFormValues(t, r, vs)
testHeader(t, r, "Range", "bytes=0-3")
fmt.Fprint(w, `hello`)
strRange := r.Header.Get("Range")
slice1 := strings.Split(strRange, "=")
slice2 := strings.Split(slice1[1], "-")
start, _ := strconv.ParseInt(slice2[0], 10, 64)
end, _ := strconv.ParseInt(slice2[1], 10, 64)
io.Copy(w, bytes.NewBuffer(data[start:end+1]))
})
for i := 0; i < 3; i++ {
math_rand.Seed(time.Now().UnixNano())
rangeStart := math_rand.Intn(contentLength)
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
continue
}
opt := &ObjectGetOptions{
ResponseContentType: "text/html",
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
}
resp, err := client.Object.Get(context.Background(), name, opt)
if err != nil {
t.Fatalf("Object.Get returned error: %v", err)
}
b, _ := ioutil.ReadAll(resp.Body)
if bytes.Compare(b, data[rangeStart:rangeEnd+1]) != 0 {
t.Errorf("Object.Get Failed")
}
}
}
func TestObjectService_GetToFile(t *testing.T) {
setup()
defer teardown()
name := "test/hello.txt"
data := make([]byte, 1024*1024*10)
rand.Read(data)
mux.HandleFunc("/test/hello.txt", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
vs := values{
"response-content-type": "text/html",
}
testFormValues(t, r, vs)
testHeader(t, r, "Range", "bytes=0-3")
io.Copy(w, bytes.NewReader(data))
})
opt := &ObjectGetOptions{
ResponseContentType: "text/html",
Range: "bytes=0-3",
}
resp, err := client.Object.Get(context.Background(), name, opt)
filePath := "test.file" + time.Now().Format(time.RFC3339)
_, err := client.Object.GetToFile(context.Background(), name, filePath, opt)
if err != nil {
t.Fatalf("Object.Get returned error: %v", err)
}
b, _ := ioutil.ReadAll(resp.Body)
ref := string(b)
want := "hello"
if !reflect.DeepEqual(ref, want) {
t.Errorf("Object.Get returned %+v, want %+v", ref, want)
defer os.Remove(filePath)
fd, err := os.Open(filePath)
if err != nil {
}
defer fd.Close()
bs, _ := ioutil.ReadAll(fd)
if bytes.Compare(bs, data) != 0 {
t.Errorf("Object.GetToFile data isn't consistent")
}
}
func TestObjectService_Put(t *testing.T) {
@ -132,6 +177,7 @@ func TestObjectService_PutFromFile(t *testing.T) {
opt := &ObjectPutOptions{
ObjectPutHeaderOptions: &ObjectPutHeaderOptions{
ContentType: "text/html",
Listener: &DefaultProgressListener{},
},
ACLHeaderOptions: &ACLHeaderOptions{
XCosACL: "private",
@ -590,3 +636,108 @@ func TestObjectService_Download(t *testing.T) {
t.Fatalf("Object.Upload returned error: %v", err)
}
}
func TestObjectService_GetTagging(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
vs := values{
"tagging": "",
}
testFormValues(t, r, vs)
fmt.Fprint(w, `<Tagging>
<TagSet>
<Tag>
<Key>test_k2</Key>
<Value>test_v2</Value>
</Tag>
<Tag>
<Key>test_k3</Key>
<Value>test_vv</Value>
</Tag>
</TagSet>
</Tagging>`)
})
res, _, err := client.Object.GetTagging(context.Background(), "test")
if err != nil {
t.Fatalf("Object.GetTagging returned error %v", err)
}
want := &ObjectGetTaggingResult{
XMLName: xml.Name{Local: "Tagging"},
TagSet: []ObjectTaggingTag{
{"test_k2", "test_v2"},
{"test_k3", "test_vv"},
},
}
if !reflect.DeepEqual(res, want) {
t.Errorf("Object.GetTagging returned %+v, want %+v", res, want)
}
}
func TestObjectService_PutTagging(t *testing.T) {
setup()
defer teardown()
opt := &ObjectPutTaggingOptions{
TagSet: []ObjectTaggingTag{
{
Key: "test_k2",
Value: "test_v2",
},
{
Key: "test_k3",
Value: "test_v3",
},
},
}
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
v := new(ObjectPutTaggingOptions)
xml.NewDecoder(r.Body).Decode(v)
testMethod(t, r, "PUT")
vs := values{
"tagging": "",
}
testFormValues(t, r, vs)
want := opt
want.XMLName = xml.Name{Local: "Tagging"}
if !reflect.DeepEqual(v, want) {
t.Errorf("Object.PutTagging request body: %+v, want %+v", v, want)
}
})
_, err := client.Object.PutTagging(context.Background(), "test", opt)
if err != nil {
t.Fatalf("Object.PutTagging returned error: %v", err)
}
}
func TestObjectService_DeleteTagging(t *testing.T) {
setup()
defer teardown()
mux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodDelete)
vs := values{
"tagging": "",
}
testFormValues(t, r, vs)
w.WriteHeader(http.StatusNoContent)
})
_, err := client.Object.DeleteTagging(context.Background(), "test")
if err != nil {
t.Fatalf("Object.DeleteTagging returned error: %v", err)
}
}
Loading…
Cancel
Save