From 2f480cee685df99a8b183b94a7152a80fb4e14a8 Mon Sep 17 00:00:00 2001 From: jojo <agin719@126.com> Date: Tue, 20 Aug 2019 20:19:22 +0800 Subject: [PATCH] add bucket website and domain interface --- bucket_domain.go | 39 ++++++++++ bucket_domain_test.go | 113 +++++++++++++++++++++++++++++ bucket_website.go | 59 +++++++++++++++ bucket_website_test.go | 166 +++++++++++++++++++++++++++++++++++++++++++ costesting/ci_test.go | 40 ++++++++++- example/bucket/delWebsite.go | 35 +++++++++ example/bucket/getDomain.go | 35 +++++++++ example/bucket/getWebsite.go | 35 +++++++++ example/bucket/putDomain.go | 42 +++++++++++ example/bucket/putWebsite.go | 53 ++++++++++++++ 10 files changed, 614 insertions(+), 3 deletions(-) create mode 100644 bucket_domain.go create mode 100644 bucket_domain_test.go create mode 100644 bucket_website.go create mode 100644 bucket_website_test.go create mode 100644 example/bucket/delWebsite.go create mode 100644 example/bucket/getDomain.go create mode 100644 example/bucket/getWebsite.go create mode 100644 example/bucket/putDomain.go create mode 100644 example/bucket/putWebsite.go diff --git a/bucket_domain.go b/bucket_domain.go new file mode 100644 index 0000000..87f78b6 --- /dev/null +++ b/bucket_domain.go @@ -0,0 +1,39 @@ +package cos + +import ( + "context" + "encoding/xml" + "net/http" +) + +type BucketPutDomainOptions struct { + XMLName xml.Name `xml:"DomainConfiguration"` + Status string `xml:"DomainRule>Status,omitempty"` + Name string `xml:"DomainRule>Name,omitempty"` + Type string `xml:"DomainRule>Type,omitempty"` + ForcedReplacement string `xml:"DomainRule>ForcedReplacement,omitempty"` +} +type BucketGetDomainResult BucketPutDomainOptions + +func (s *BucketService) PutDomain(ctx context.Context, opt *BucketPutDomainOptions) (*Response, error) { + sendOpt := &sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?domain", + method: http.MethodPut, + body: opt, + } + resp, err := s.client.send(ctx, sendOpt) + return resp, err +} + +func (s *BucketService) GetDomain(ctx context.Context) (*BucketGetDomainResult, *Response, error) { + var res BucketGetDomainResult + sendOpt := &sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?domain", + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, sendOpt) + return &res, resp, err +} diff --git a/bucket_domain_test.go b/bucket_domain_test.go new file mode 100644 index 0000000..896e68f --- /dev/null +++ b/bucket_domain_test.go @@ -0,0 +1,113 @@ +package cos + +import ( + "context" + "encoding/xml" + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestBucketService_GetDomain(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + vs := values{ + "domain": "", + } + testFormValues(t, r, vs) + fmt.Fprint(w, `<DomainConfiguration> + <DomainRule> + <Status>ENABLED</Status> + <Name>www.abc.com</Name> + <Type>REST</Type> + <ForcedReplacement>CNAME</ForcedReplacement> + </DomainRule> +</DomainConfiguration>`) + }) + + res, _, err := client.Bucket.GetDomain(context.Background()) + if err != nil { + t.Fatalf("Bucket.GetDomain returned error %v", err) + } + + want := &BucketGetDomainResult{ + XMLName: xml.Name{Local: "DomainConfiguration"}, + Status: "ENABLED", + Name: "www.abc.com", + Type: "REST", + ForcedReplacement: "CNAME", + } + + if !reflect.DeepEqual(res, want) { + t.Errorf("Bucket.GetDomain returned %+v, want %+v", res, want) + } +} + +func TestBucketService_PutDomain(t *testing.T) { + setup() + defer teardown() + + opt := &BucketPutDomainOptions{ + XMLName: xml.Name{Local: "DomainConfiguration"}, + Status: "ENABLED", + Name: "www.abc.com", + Type: "REST", + ForcedReplacement: "CNAME", + } + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + vs := values{ + "domain": "", + } + testFormValues(t, r, vs) + + body := new(BucketPutDomainOptions) + xml.NewDecoder(r.Body).Decode(body) + want := opt + want.XMLName = xml.Name{Local: "DomainConfiguration"} + if !reflect.DeepEqual(body, want) { + t.Errorf("Bucket.PutDomain request\n body: %+v\n, want %+v\n", body, want) + } + }) + + _, err := client.Bucket.PutDomain(context.Background(), opt) + if err != nil { + t.Fatalf("Bucket.PutDomain returned error: %v", err) + } +} + +func TestBucketService_DeleteDomain(t *testing.T) { + setup() + defer teardown() + + opt := &BucketPutDomainOptions{} + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPut) + vs := values{ + "domain": "", + } + testFormValues(t, r, vs) + + body := new(BucketPutDomainOptions) + xml.NewDecoder(r.Body).Decode(body) + want := opt + want.XMLName = xml.Name{Local: "DomainConfiguration"} + if !reflect.DeepEqual(body, want) { + t.Errorf("Bucket.PutDomain request\n body: %+v\n, want %+v\n", body, want) + } + + w.WriteHeader(http.StatusNoContent) + }) + + _, err := client.Bucket.PutDomain(context.Background(), opt) + if err != nil { + t.Fatalf("Bucket.PutDomain returned error: %v", err) + } + +} diff --git a/bucket_website.go b/bucket_website.go new file mode 100644 index 0000000..3052bf1 --- /dev/null +++ b/bucket_website.go @@ -0,0 +1,59 @@ +package cos + +import ( + "context" + "encoding/xml" + "net/http" +) + +type WebsiteRoutingRule struct { + ConditionErrorCode string `xml:"Condition>HttpErrorCodeReturnedEquals,omitempty"` + ConditionPrefix string `xml:"Condition>KeyPrefixEquals,omitempty"` + + RedirectProtocol string `xml:"Redirect>Protocol,omitempty"` + RedirectReplaceKey string `xml:"Redirect>ReplaceKeyWith,omitempty"` + RedirectReplaceKeyPrefix string `xml:"Redirect>ReplaceKeyPrefixWith,omitempty"` +} + +type BucketPutWebsiteOptions struct { + XMLName xml.Name `xml:"WebsiteConfiguration"` + Index string `xml:"IndexDocument>Suffix"` + RedirectProtocol string `xml:"RedirectAllRequestsTo>Protocol,omitempty"` + Error string `xml:"ErrorDocument>Key,omitempty"` + Rules []WebsiteRoutingRule `xml:"RoutingRules>RoutingRule,omitempty"` +} + +type BucketGetWebsiteResult BucketPutWebsiteOptions + +func (s *BucketService) PutWebsite(ctx context.Context, opt *BucketPutWebsiteOptions) (*Response, error) { + sendOpt := &sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?website", + method: http.MethodPut, + body: opt, + } + resp, err := s.client.send(ctx, sendOpt) + return resp, err +} + +func (s *BucketService) GetWebsite(ctx context.Context) (*BucketGetWebsiteResult, *Response, error) { + var res BucketGetWebsiteResult + sendOpt := &sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?website", + method: http.MethodGet, + result: &res, + } + resp, err := s.client.send(ctx, sendOpt) + return &res, resp, err +} + +func (s *BucketService) DeleteWebsite(ctx context.Context) (*Response, error) { + sendOpt := &sendOptions{ + baseURL: s.client.BaseURL.BucketURL, + uri: "/?website", + method: http.MethodDelete, + } + resp, err := s.client.send(ctx, sendOpt) + return resp, err +} diff --git a/bucket_website_test.go b/bucket_website_test.go new file mode 100644 index 0000000..c59bcc8 --- /dev/null +++ b/bucket_website_test.go @@ -0,0 +1,166 @@ +package cos + +import ( + "context" + "encoding/xml" + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestBucketService_GetWebsite(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + vs := values{ + "website": "", + } + testFormValues(t, r, vs) + fmt.Fprint(w, `<WebsiteConfiguration> + <IndexDocument> + <Suffix>index.html</Suffix> + </IndexDocument> + <RedirectAllRequestsTo> + <Protocol>https</Protocol> + </RedirectAllRequestsTo> + <ErrorDocument> + <Key>Error.html</Key> + </ErrorDocument> + <RoutingRules> + <RoutingRule> + <Condition> + <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals> + </Condition> + <Redirect> + <Protocol>https</Protocol> + <ReplaceKeyWith>404.html</ReplaceKeyWith> + </Redirect> + </RoutingRule> + <RoutingRule> + <Condition> + <KeyPrefixEquals>docs/</KeyPrefixEquals> + </Condition> + <Redirect> + <Protocol>https</Protocol> + <ReplaceKeyPrefixWith>documents/</ReplaceKeyPrefixWith> + </Redirect> + </RoutingRule> + <RoutingRule> + <Condition> + <KeyPrefixEquals>img/</KeyPrefixEquals> + </Condition> + <Redirect> + <Protocol>https</Protocol> + <ReplaceKeyWith>demo.jpg</ReplaceKeyWith> + </Redirect> + </RoutingRule> + </RoutingRules> +</WebsiteConfiguration>`) + }) + + res, _, err := client.Bucket.GetWebsite(context.Background()) + if err != nil { + t.Fatalf("Bucket.GetWebsite returned error %v", err) + } + + want := &BucketGetWebsiteResult{ + XMLName: xml.Name{Local: "WebsiteConfiguration"}, + Index: "index.html", + RedirectProtocol: "https", + Error: "Error.html", + Rules: []WebsiteRoutingRule{ + { + ConditionErrorCode: "404", + RedirectProtocol: "https", + RedirectReplaceKey: "404.html", + }, + { + ConditionPrefix: "docs/", + RedirectProtocol: "https", + RedirectReplaceKeyPrefix: "documents/", + }, + { + ConditionPrefix: "img/", + RedirectProtocol: "https", + RedirectReplaceKey: "demo.jpg", + }, + }, + } + + if !reflect.DeepEqual(res, want) { + t.Errorf("Bucket.GetWebsite returned %+v, want %+v", res, want) + } +} + +func TestBucketService_PutWebsite(t *testing.T) { + setup() + defer teardown() + + opt := &BucketPutWebsiteOptions{ + Index: "index.html", + RedirectProtocol: "https", + Error: "Error.html", + Rules: []WebsiteRoutingRule{ + { + ConditionErrorCode: "404", + RedirectProtocol: "https", + RedirectReplaceKey: "404.html", + }, + { + ConditionPrefix: "docs/", + RedirectProtocol: "https", + RedirectReplaceKeyPrefix: "documents/", + }, + { + ConditionPrefix: "img/", + RedirectProtocol: "https", + RedirectReplaceKey: "demo.jpg", + }, + }, + } + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PUT") + vs := values{ + "website": "", + } + testFormValues(t, r, vs) + + body := new(BucketPutWebsiteOptions) + xml.NewDecoder(r.Body).Decode(body) + want := opt + want.XMLName = xml.Name{Local: "WebsiteConfiguration"} + if !reflect.DeepEqual(body, want) { + t.Errorf("Bucket.PutWebsite request\n body: %+v\n, want %+v\n", body, want) + } + }) + + _, err := client.Bucket.PutWebsite(context.Background(), opt) + if err != nil { + t.Fatalf("Bucket.PutWebsite returned error: %v", err) + } +} + +func TestBucketService_DeleteWebsite(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + vs := values{ + "website": "", + } + testFormValues(t, r, vs) + + w.WriteHeader(http.StatusNoContent) + }) + + _, err := client.Bucket.DeleteWebsite(context.Background()) + if err != nil { + t.Fatalf("Bucket.DeleteWebsite returned error: %v", err) + } + +} diff --git a/costesting/ci_test.go b/costesting/ci_test.go index ea2dc59..8e485ee 100644 --- a/costesting/ci_test.go +++ b/costesting/ci_test.go @@ -4,9 +4,6 @@ package cos import ( "context" "fmt" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/suite" - "github.com/tencentyun/cos-go-sdk-v5" "io/ioutil" "math/rand" "net/http" @@ -15,6 +12,10 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "github.com/tencentyun/cos-go-sdk-v5" ) // Define the suite, and absorb the built-in basic suite @@ -304,6 +305,39 @@ func (s *CosTestSuite) TestPutGetDeleteLifeCycle() { assert.Nil(s.T(), err, "DeleteBucketLifecycle Failed") } +func (s *CosTestSuite) TestPutGetDeleteWebsite() { + opt := &cos.BucketPutWebsiteOptions{ + Index: "index.html", + Error: "index_backup.html", + RedirectProtocol: "https", + Rules: []cos.WebsiteRoutingRule{ + { + ConditionErrorCode: "404", + RedirectProtocol: "https", + RedirectReplaceKey: "404.html", + }, + { + ConditionPrefix: "docs/", + RedirectProtocol: "https", + RedirectReplaceKeyPrefix: "documents/", + }, + }, + } + + _, err := s.Client.Bucket.PutWebsite(context.Background(), opt) + assert.Nil(s.T(), err, "PutBucketWebsite Failed") + + res, rsp, err := s.Client.Bucket.GetWebsite(context.Background()) + if err != nil && 404 != rsp.StatusCode { + assert.Nil(s.T(), err, "GetBucketWebsite Failed") + } + assert.Equal(s.T(), opt.Index, res.Index, "GetBucketWebsite Failed") + assert.Equal(s.T(), opt.Error, res.Error, "GetBucketWebsite Failed") + assert.Equal(s.T(), opt.RedirectProtocol, res.RedirectProtocol, "GetBucketWebsite Failed") + _, err = s.Client.Bucket.DeleteWebsite(context.Background()) + assert.Nil(s.T(), err, "DeleteBucketWebsite Failed") +} + func (s *CosTestSuite) TestListMultipartUploads() { // Create new upload name := "test_multipart" + time.Now().Format(time.RFC3339) diff --git a/example/bucket/delWebsite.go b/example/bucket/delWebsite.go new file mode 100644 index 0000000..4741490 --- /dev/null +++ b/example/bucket/delWebsite.go @@ -0,0 +1,35 @@ +package main + +import ( + "context" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +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, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + _, err := c.Bucket.DeleteWebsite(context.Background()) + if err != nil { + panic(err) + } +} diff --git a/example/bucket/getDomain.go b/example/bucket/getDomain.go new file mode 100644 index 0000000..0de5e0d --- /dev/null +++ b/example/bucket/getDomain.go @@ -0,0 +1,35 @@ +package main + +import ( + "context" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +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, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + _, _, err := c.Bucket.GetDomain(context.Background()) + if err != nil { + panic(err) + } +} diff --git a/example/bucket/getWebsite.go b/example/bucket/getWebsite.go new file mode 100644 index 0000000..78b82c4 --- /dev/null +++ b/example/bucket/getWebsite.go @@ -0,0 +1,35 @@ +package main + +import ( + "context" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +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, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + _, _, err := c.Bucket.GetWebsite(context.Background()) + if err != nil { + panic(err) + } +} diff --git a/example/bucket/putDomain.go b/example/bucket/putDomain.go new file mode 100644 index 0000000..e14968b --- /dev/null +++ b/example/bucket/putDomain.go @@ -0,0 +1,42 @@ +package main + +import ( + "context" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +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, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + opt := &cos.BucketPutDomainOptions{ + Status: "ENABLED", + Name: "www.abc.com", + Type: "REST", + ForcedReplacement: "CNAME", + } + + _, err := c.Bucket.PutDomain(context.Background(), opt) + if err != nil { + panic(err) + } +} diff --git a/example/bucket/putWebsite.go b/example/bucket/putWebsite.go new file mode 100644 index 0000000..c87fb23 --- /dev/null +++ b/example/bucket/putWebsite.go @@ -0,0 +1,53 @@ +package main + +import ( + "context" + "net/http" + "net/url" + "os" + + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" +) + +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, + RequestBody: true, + ResponseHeader: true, + ResponseBody: true, + }, + }, + }) + + opt := &cos.BucketPutWebsiteOptions{ + Index: "index.html", + Error: "index_backup.html", + RedirectProtocol: "https", + Rules: []cos.WebsiteRoutingRule{ + { + ConditionErrorCode: "404", + RedirectProtocol: "https", + RedirectReplaceKey: "404.html", + }, + { + ConditionPrefix: "docs/", + RedirectProtocol: "https", + RedirectReplaceKeyPrefix: "documents/", + }, + }, + } + + _, err := c.Bucket.PutWebsite(context.Background(), opt) + if err != nil { + panic(err) + } +}