From b97ada9dbd6b499e083396e53bc16ff9a5157330 Mon Sep 17 00:00:00 2001 From: yangpeng Date: Mon, 24 Apr 2023 14:06:00 +0800 Subject: [PATCH] add bucket callback policy api --- oss/client.go | 76 ++++++++++++++++++++++++ oss/client_test.go | 79 +++++++++++++++++++++++++ oss/type.go | 18 ++++++ oss/type_test.go | 58 +++++++++++++++++- sample.go | 1 + sample/bucket_callbackpolicy.go | 100 ++++++++++++++++++++++++++++++++ 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 sample/bucket_callbackpolicy.go diff --git a/oss/client.go b/oss/client.go index 297d2f3..74a7c5e 100644 --- a/oss/client.go +++ b/oss/client.go @@ -2492,6 +2492,82 @@ func (client Client) DeleteBucketStyle(bucketName, styleName string, options ... return CheckRespCode(resp.StatusCode, []int{http.StatusNoContent}) } +// GetBucketCallbackPolicy get bucket's callback policy +// bucketName the bucket name. +// error it's nil if no error, otherwise it's an error object. +func (client Client) GetBucketCallbackPolicy(bucketName string, options ...Option) (GetBucketCallbackPolicyResult, error) { + var out GetBucketCallbackPolicyResult + body, err := client.GetBucketCallbackPolicyXml(bucketName, options...) + err = xmlUnmarshal(strings.NewReader(body), &out) + return out, err +} + +// GetBucketCallbackPolicyXml get bucket's callback policy +// bucketName the bucket name. +// string the call back policy of bucket in xml format. +// error it's nil if no error, otherwise it's an error object. +func (client Client) GetBucketCallbackPolicyXml(bucketName string, options ...Option) (string, error) { + params := map[string]interface{}{} + params["policy"] = nil + params["comp"] = "callback" + resp, err := client.do("GET", bucketName, params, nil, nil, options...) + if err != nil { + return "", err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + out := string(body) + return out, err +} + +// PutBucketCallbackPolicy set bucket's callback policy +// bucketName the bucket name. +// callbackPolicy PutBucketCallbackPolicy the call back policy of bucket in struct format. +// error it's nil if no error, otherwise it's an error object. +func (client Client) PutBucketCallbackPolicy(bucketName string, callbackPolicy PutBucketCallbackPolicy, options ...Option) error { + bs, err := xml.Marshal(callbackPolicy) + if err != nil { + return err + } + err = client.PutBucketCallbackPolicyXml(bucketName, string(bs), options...) + return err +} + +// DeleteBucketCallbackPolicy delete bucket's callback policy +// bucketName the bucket name. +// error it's nil if no error, otherwise it's an error object. +func (client Client) DeleteBucketCallbackPolicy(bucketName string, options ...Option) error { + params := map[string]interface{}{} + params["policy"] = nil + params["comp"] = "callback" + resp, err := client.do("DELETE", bucketName, params, nil, nil, options...) + if err != nil { + return err + } + defer resp.Body.Close() + return CheckRespCode(resp.StatusCode, []int{http.StatusNoContent}) +} + +// PutBucketCallbackPolicyXml set bucket's callback policy +// bucketName the bucket name. +// xmlData the call back policy of bucket in xml format. +// error it's nil if no error, otherwise it's an error object. +func (client Client) PutBucketCallbackPolicyXml(bucketName, xmlData string, options ...Option) error { + buffer := new(bytes.Buffer) + buffer.Write([]byte(xmlData)) + headers := map[string]string{} + headers[HTTPHeaderContentType] = "application/xml" + params := map[string]interface{}{} + params["policy"] = nil + params["comp"] = "callback" + resp, err := client.do("PUT", bucketName, params, headers, buffer, options...) + if err != nil { + return err + } + defer resp.Body.Close() + return CheckRespCode(resp.StatusCode, []int{http.StatusOK}) +} + // LimitUploadSpeed set upload bandwidth limit speed,default is 0,unlimited // upSpeed KB/s, 0 is unlimited,default is 0 // error it's nil if success, otherwise failure diff --git a/oss/client_test.go b/oss/client_test.go index 2356264..781216c 100644 --- a/oss/client_test.go +++ b/oss/client_test.go @@ -5,6 +5,8 @@ package oss import ( + "bytes" + "encoding/base64" "encoding/json" "encoding/xml" "fmt" @@ -5505,3 +5507,80 @@ func (s *OssClientSuite) TestBucketStyle(c *C) { c.Assert(err, IsNil) } + +// TestBucketCallbackPolicy +func (s *OssClientSuite) TestBucketCallbackPolicy(c *C) { + var bucketNameTest = bucketNamePrefix + "-acc-" + RandLowStr(6) + client, err := New(endpoint, accessID, accessKey) + c.Assert(err, IsNil) + + err = client.CreateBucket(bucketNameTest) + c.Assert(err, IsNil) + time.Sleep(3 * time.Second) + + // Put Bucket Callback Policy + var callbackPolicy PutBucketCallbackPolicy + callbackVal := base64.StdEncoding.EncodeToString([]byte(`{"callbackUrl":"http://www.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}"}`)) + + callbackVal2 := base64.StdEncoding.EncodeToString([]byte(`{"callbackUrl":"http://www.aliyun.com", "callbackBody":"bucket=${bucket}&object=${object}"}`)) + + callbackVar2 := base64.StdEncoding.EncodeToString([]byte(`{"x:a":"a", "x:b":"b"}`)) + callbackPolicy = PutBucketCallbackPolicy{ + PolicyItem: []PolicyItem{ + { + PolicyName: "first", + Callback: callbackVal, + CallbackVar: "", + }, + { + PolicyName: "second", + Callback: callbackVal2, + CallbackVar: callbackVar2, + }, + }, + } + + err = client.PutBucketCallbackPolicy(bucketNameTest, callbackPolicy) + c.Assert(err, IsNil) + + time.Sleep(time.Second * 3) + + // get bucket callback policy + res, err := client.GetBucketCallbackPolicy(bucketNameTest) + c.Assert(err, IsNil) + c.Assert(len(res.PolicyItem), Equals, 2) + + bucket, err := client.Bucket(bucketNameTest) + + name := base64.StdEncoding.EncodeToString([]byte(`{"callbackPolicy":"first"}`)) + err = bucket.PutObject("object.txt", strings.NewReader("hi oss"), Callback(name)) + c.Assert(err, NotNil) + c.Assert(err.(UnexpectedStatusCodeError).Got(), Equals, 203) + + name = base64.StdEncoding.EncodeToString([]byte(`{"callbackPolicy":"not_exist_name"}`)) + err = bucket.PutObject("object.txt", strings.NewReader("hi oss"), Callback(name)) + c.Assert(err, NotNil) + + name = base64.StdEncoding.EncodeToString([]byte(`{"callbackPolicy":"not_exist_name"}`)) + callbackMap := map[string]string{} + callbackMap["callbackUrl"] = "http://oss-demo.aliyuncs.com:23451" + callbackMap["callbackHost"] = "oss-cn-hangzhou.aliyuncs.com" + callbackMap["callbackBody"] = "filename=${object}&size=${size}&mimeType=${mimeType}" + callbackMap["callbackBodyType"] = "application/x-www-form-urlencoded" + callbackMap["callbackPolicy"] = "first" + callbackBuffer := bytes.NewBuffer([]byte{}) + callbackEncoder := json.NewEncoder(callbackBuffer) + //do not encode '&' to "\u0026" + callbackEncoder.SetEscapeHTML(false) + err = callbackEncoder.Encode(callbackMap) + c.Assert(err, IsNil) + callbackVal3 := base64.StdEncoding.EncodeToString(callbackBuffer.Bytes()) + err = bucket.PutObject("object.txt", strings.NewReader("hi oss"), Callback(callbackVal3)) + c.Assert(err, NotNil) + + // delete bucket style + err = client.DeleteBucketCallbackPolicy(bucketNameTest) + c.Assert(err, IsNil) + + ForceDeleteBucket(client, bucketNameTest, c) +} diff --git a/oss/type.go b/oss/type.go index 852d5e3..505acb6 100644 --- a/oss/type.go +++ b/oss/type.go @@ -1633,3 +1633,21 @@ type BucketStyleXml struct { CreateTime string `xml:"CreateTime,omitempty"` // style create time LastModifyTime string `xml:"LastModifyTime,omitempty"` // style last modify time } + +// GetBucketCallbackPolicyResult define the callback policy for the bucket +type GetBucketCallbackPolicyResult BucketCallbackPolicyXml + +// PutBucketCallbackPolicy define the callback policy for the bucket +type PutBucketCallbackPolicy BucketCallbackPolicyXml + +// BucketCallbackPolicyXml define the callback policy of the bucket +type BucketCallbackPolicyXml struct { + XMLName xml.Name `xml:"BucketCallbackPolicy"` + PolicyItem []PolicyItem `xml:"PolicyItem"` +} + +type PolicyItem struct { + PolicyName string `xml:"PolicyName"` + Callback string `xml:"Callback"` + CallbackVar string `xml:"CallbackVar"` +} diff --git a/oss/type_test.go b/oss/type_test.go index 15bf644..b8b18a8 100644 --- a/oss/type_test.go +++ b/oss/type_test.go @@ -1,6 +1,7 @@ package oss import ( + "encoding/base64" "encoding/xml" "net/url" "sort" @@ -1529,4 +1530,59 @@ func (s *OssTypeSuite) TestGetBucketReplicationProgressResult(c *C) { c.Assert(repResult.Rule[0].HistoricalObjectReplication, Equals, "enabled") c.Assert((*repResult.Rule[0].Progress).HistoricalObject, Equals, "0.85") c.Assert((*repResult.Rule[0].Progress).NewObject, Equals, "2015-09-24T15:28:14.000Z") -} \ No newline at end of file +} + +func (s *OssTypeSuite) TestGetBucketCallbackPolicyResult(c *C) { + xmlData := ` + + + first + e1wiY2FsR7YnU= + Q2FsbGmJcIn0= + + + second + e1wiY2Fsb9keVwiOlwiYnVja2V0PSR7YnU= + Q2FsFcIiwgXCJ4OmJcIjpcImJcIn0= + +` + var repResult GetBucketCallbackPolicyResult + err := xmlUnmarshal(strings.NewReader(xmlData), &repResult) + c.Assert(err, IsNil) + c.Assert(repResult.PolicyItem[0].PolicyName, Equals, "first") + c.Assert(repResult.PolicyItem[0].Callback, Equals, "e1wiY2FsR7YnU=") + c.Assert(repResult.PolicyItem[0].CallbackVar, Equals, "Q2FsbGmJcIn0=") + + c.Assert(repResult.PolicyItem[1].PolicyName, Equals, "second") + c.Assert(repResult.PolicyItem[1].Callback, Equals, "e1wiY2Fsb9keVwiOlwiYnVja2V0PSR7YnU=") + c.Assert(repResult.PolicyItem[1].CallbackVar, Equals, "Q2FsFcIiwgXCJ4OmJcIjpcImJcIn0=") +} + +func (s *OssTypeSuite) TestPutBucketCallbackPolicy(c *C) { + xmlData := `firsteyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuYWxpeXVuY3MuY29tIiwgImNhbGxiYWNrQm9keSI6ImJ1Y2tldD0ke2J1Y2tldH0mb2JqZWN0PSR7b2JqZWN0fSJ9secondeyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuYWxpeXVuLmNvbSIsICJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0ifQ==eyJ4OmEiOiJhIiwgIng6YiI6ImIifQ==` + var callbackPolicy PutBucketCallbackPolicy + callbackVal := base64.StdEncoding.EncodeToString([]byte(`{"callbackUrl":"http://www.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}"}`)) + + callbackVal2 := base64.StdEncoding.EncodeToString([]byte(`{"callbackUrl":"http://www.aliyun.com", "callbackBody":"bucket=${bucket}&object=${object}"}`)) + + callbackVar2 := base64.StdEncoding.EncodeToString([]byte(`{"x:a":"a", "x:b":"b"}`)) + callbackPolicy = PutBucketCallbackPolicy{ + PolicyItem: []PolicyItem{ + { + PolicyName: "first", + Callback: callbackVal, + CallbackVar: "", + }, + { + PolicyName: "second", + Callback: callbackVal2, + CallbackVar: callbackVar2, + }, + }, + } + bs, err := xml.Marshal(callbackPolicy) + c.Assert(err, IsNil) + testLogger.Println(string(bs)) + c.Assert(string(bs), Equals, xmlData) + +} diff --git a/sample.go b/sample.go index 72fe905..c5ccdf4 100644 --- a/sample.go +++ b/sample.go @@ -34,6 +34,7 @@ var sampleMap = map[string]interface{}{ "BucketCnameSample": sample.BucketCnameSample, "BucketStyleSample": sample.BucketStyleSample, "BucketReplicationSample": sample.BucketReplicationSample, + "BucketCallbackPolicySample": sample.BucketCallbackPolicySample, "ObjectACLSample": sample.ObjectACLSample, "ObjectMetaSample": sample.ObjectMetaSample, "ListObjectsSample": sample.ListObjectsSample, diff --git a/sample/bucket_callbackpolicy.go b/sample/bucket_callbackpolicy.go new file mode 100644 index 0000000..34aae48 --- /dev/null +++ b/sample/bucket_callbackpolicy.go @@ -0,0 +1,100 @@ +package sample + +import ( + "encoding/base64" + "fmt" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "os" + "strings" +) + +// BucketCallbackPolicySample shows how to set, get and delete the bucket callback policy configuration +func BucketCallbackPolicySample() { + // New client + client, err := oss.New(endpoint, accessID, accessKey) + if err != nil { + HandleError(err) + } + + // Create the bucket with default parameters + err = client.CreateBucket(bucketName) + if err != nil { + HandleError(err) + } + + // the policy string + var callbackPolicy oss.PutBucketCallbackPolicy + callbackVal := base64.StdEncoding.EncodeToString([]byte(`{"callbackUrl":"http://www.aliyuncs.com", "callbackBody":"bucket=${bucket}&object=${object}"}`)) + + callbackVal2 := base64.StdEncoding.EncodeToString([]byte(`{"callbackUrl":"http://www.aliyun.com", "callbackBody":"bucket=${bucket}&object=${object}"}`)) + + callbackVar2 := base64.StdEncoding.EncodeToString([]byte(`{"x:a":"a", "x:b":"b"}`)) + callbackPolicy = oss.PutBucketCallbackPolicy{ + PolicyItem: []oss.PolicyItem{ + { + PolicyName: "first", + Callback: callbackVal, + CallbackVar: "", + }, + { + PolicyName: "second", + Callback: callbackVal2, + CallbackVar: callbackVar2, + }, + }, + } + + // Set callback policy + err = client.PutBucketCallbackPolicy(bucketName, callbackPolicy) + if err != nil { + HandleError(err) + } + + fmt.Println("Put Bucket Callback Policy Success!") + + // Get Bucket policy + result, err := client.GetBucketCallbackPolicy(bucketName) + if err != nil { + HandleError(err) + } + for _, policy := range result.PolicyItem { + fmt.Printf("Callback Policy Name:%s\n", policy.PolicyName) + + callback, _ := base64.StdEncoding.DecodeString(policy.Callback) + fmt.Printf("Callback Policy Callback:%s\n", callback) + if policy.CallbackVar != "" { + callbackVar, _ := base64.StdEncoding.DecodeString(policy.CallbackVar) + fmt.Printf("Callback Policy Callback Var:%s\n", callbackVar) + } + } + fmt.Println("Get Bucket Callback Policy Success!") + + // Delete Bucket policy + err = client.DeleteBucketCallbackPolicy(bucketName) + if err != nil { + HandleError(err) + } + fmt.Println("Delete Bucket Callback Policy Success!") + + // put object by use callback policy + bucket, err := client.Bucket(bucketName) + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + name := base64.StdEncoding.EncodeToString([]byte(`{"callbackPolicy":"first"}`)) + err = bucket.PutObject("example-object.txt", strings.NewReader("Hello OSS"), oss.Callback(name)) + if err != nil { + fmt.Println("Error:", err) + os.Exit(-1) + } + fmt.Println("Use Callback Policy Success!") + + // Delete bucket + err = client.DeleteBucket(bucketName) + if err != nil { + HandleError(err) + } + + fmt.Println("BucketCallbackPolicySample completed") +}