Browse Source

add request payment api

alzhang 6 years ago
parent
commit
c7e2d4290f
10 changed files with 885 additions and 26 deletions
  1. 615 0
      oss/bucket_credential_test.go
  2. 61 0
      oss/client.go
  3. 51 0
      oss/client_test.go
  4. 1 1
      oss/conn.go
  5. 4 1
      oss/const.go
  6. 1 1
      oss/option.go
  7. 6 0
      oss/type.go
  8. 24 23
      sample.go
  9. 117 0
      sample/bucket_requestpayment.go
  10. 5 0
      sample/config.go

+ 615 - 0
oss/bucket_credential_test.go

@@ -0,0 +1,615 @@
+// Credentials test
+package oss
+
+import (
+	"os"
+	"strings"
+	"io/ioutil"
+	"math/rand"
+	"bytes"
+	"strconv"
+	. "gopkg.in/check.v1"
+)
+
+type OssCredentialBucketSuite struct {
+	client        *Client
+	creClient     *Client
+	bucket        *Bucket
+	creBucket     *Bucket
+}
+
+var _ = Suite(&OssCredentialBucketSuite{})
+
+func (cs *OssCredentialBucketSuite)credentialSubUser(c *C) {
+	client, err := New(endpoint, accessID, accessKey)
+	c.Assert(err, IsNil)
+	err = client.CreateBucket(credentialBucketName)
+	c.Assert(err, IsNil)
+	cs.client = client
+	policyInfo := `
+	{
+		"Version":"1",
+		"Statement":[
+			{
+				"Action":[
+					"oss:*"
+				],
+				"Effect":"Allow",
+				"Principal":["`+ credentialUID + `"],
+				"Resource":["acs:oss:*:*:` + credentialBucketName + `", "acs:oss:*:*:` + credentialBucketName + `/*"]
+			}
+		]
+	}`
+
+	err = client.SetBucketPolicy(credentialBucketName, policyInfo)
+	c.Assert(err, IsNil)
+
+	bucket, err := cs.client.Bucket(credentialBucketName)
+	c.Assert(err, IsNil)
+	cs.bucket = bucket
+}
+
+// SetUpSuite runs once when the suite starts running.
+func (cs *OssCredentialBucketSuite) SetUpSuite(c *C) {
+	if credentialUID == ""{
+		testLogger.Println("the cerdential UID is NULL, skip the credential test")
+		c.Skip("the credential Uid is null")
+	}
+
+	cs.credentialSubUser(c)
+	client, err := New(endpoint, credentialAccessID, credentialAccessKey)
+	c.Assert(err, IsNil)
+	cs.creClient = client
+
+	bucket, err := cs.creClient.Bucket(credentialBucketName)
+	c.Assert(err, IsNil)
+	cs.creBucket = bucket
+
+	testLogger.Println("test credetial bucket started")
+}
+
+func (cs *OssCredentialBucketSuite) TearDownSuite(c *C) {
+	if credentialUID == ""{
+		c.Skip("the credential Uid is null")
+	}
+	for _, bucket := range []*Bucket{cs.bucket} {
+		// Delete multipart
+		keyMarker := KeyMarker("")
+		uploadIDMarker := UploadIDMarker("")
+		for {
+			lmu, err := bucket.ListMultipartUploads(keyMarker, uploadIDMarker)
+			c.Assert(err, IsNil)
+			for _, upload := range lmu.Uploads {
+				imur := InitiateMultipartUploadResult{Bucket: credentialBucketName, Key: upload.Key, UploadID: upload.UploadID}
+				err = bucket.AbortMultipartUpload(imur)
+				c.Assert(err, IsNil)
+			}
+			keyMarker = KeyMarker(lmu.NextKeyMarker)
+			uploadIDMarker = UploadIDMarker(lmu.NextUploadIDMarker)
+			if !lmu.IsTruncated {
+				break
+			}
+		}
+		// Delete objects
+		marker := Marker("")
+		for {
+			lor, err := bucket.ListObjects(marker)
+			c.Assert(err, IsNil)
+			for _, object := range lor.Objects {
+				err = bucket.DeleteObject(object.Key)
+				c.Assert(err, IsNil)
+			}
+			marker = Marker(lor.NextMarker)
+			if !lor.IsTruncated{
+				break
+			}
+		}
+	}
+	err := cs.client.DeleteBucket(credentialBucketName)
+	c.Assert(err, IsNil)
+	testLogger.Println("test credential bucket completed")
+}
+
+// Test put/get/list/delte object
+func (cs *OssCredentialBucketSuite) TestReqerPaymentNoRequester(c *C) {
+	// Set bucket is requester who send the request
+	reqPayConf := RequestPaymentConfiguration{
+		Payer:string(Requester),
+	}
+	err := cs.client.SetBucketRequestPayment(credentialBucketName, reqPayConf)
+	c.Assert(err, IsNil)
+
+	key := objectNamePrefix + randStr(8)
+	objectValue := randStr(18)
+
+	// Put object
+	err = cs.creBucket.PutObject(key, strings.NewReader(objectValue))
+	c.Assert(err, NotNil)
+
+	// Get object
+	_, err = cs.creBucket.GetObject(key)
+	c.Assert(err, NotNil)
+
+	// List object
+	_, err = cs.creBucket.ListObjects()
+	c.Assert(err, NotNil)
+
+	err = cs.creBucket.DeleteObject(key)
+	c.Assert(err, NotNil)
+
+	// Set bucket is BucketOwner
+	reqPayConf.Payer = string(BucketOwner)
+	err = cs.client.SetBucketRequestPayment(credentialBucketName, reqPayConf)
+	c.Assert(err, IsNil)
+}
+
+// Test put/get/list/delte object
+func (cs *OssCredentialBucketSuite) TestReqerPaymentWithRequester(c *C) {
+	// Set bucket is requester who send the request
+	reqPayConf := RequestPaymentConfiguration{
+		Payer:string(Requester),
+	}
+	err := cs.client.SetBucketRequestPayment(credentialBucketName, reqPayConf)
+	c.Assert(err, IsNil)
+
+	key := objectNamePrefix + randStr(8)
+	objectValue := randStr(18)
+
+	// Put object with a bucketowner
+	err = cs.creBucket.PutObject(key, strings.NewReader(objectValue), RequestPayer(BucketOwner))
+	c.Assert(err, NotNil)
+
+	// Put object
+	err = cs.creBucket.PutObject(key, strings.NewReader(objectValue), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Get object
+	body, err := cs.creBucket.GetObject(key, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	defer body.Close()
+
+	data, err := ioutil.ReadAll(body)
+	c.Assert(err, IsNil)
+	c.Assert(string(data), Equals, objectValue)
+
+	// List object
+	lor, err := cs.creBucket.ListObjects(RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(len(lor.Objects), Equals, 1)
+
+	err = cs.creBucket.DeleteObject(key, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Set bucket is BucketOwner
+	reqPayConf.Payer = string(BucketOwner)
+	err = cs.client.SetBucketRequestPayment(credentialBucketName, reqPayConf)
+	c.Assert(err, IsNil)
+}
+
+// Test put/get/list/delte object
+func (cs *OssCredentialBucketSuite) TestOwnerPaymentNoRequester(c *C) {
+	// Set bucket is requester who send the request
+	reqPayConf := RequestPaymentConfiguration{
+		Payer:string(BucketOwner),
+	}
+	err := cs.client.SetBucketRequestPayment(credentialBucketName, reqPayConf)
+	c.Assert(err, IsNil)
+
+	key := objectNamePrefix + randStr(8)
+	objectValue := randStr(18)
+
+	// Put object
+	err = cs.creBucket.PutObject(key, strings.NewReader(objectValue))
+	c.Assert(err, IsNil)
+
+	// Get object
+	body, err := cs.creBucket.GetObject(key)
+	c.Assert(err, IsNil)
+	defer body.Close()
+
+	data, err := ioutil.ReadAll(body)
+	c.Assert(err, IsNil)
+	c.Assert(string(data), Equals, objectValue)
+
+	// List object
+	lor, err := cs.creBucket.ListObjects()
+	c.Assert(err, IsNil)
+	c.Assert(len(lor.Objects), Equals, 1)
+
+	err = cs.creBucket.DeleteObject(key)
+	c.Assert(err, IsNil)
+}
+
+// Test put/get/list/delte object
+func (cs *OssCredentialBucketSuite) TestOwnerPaymentWithRequester(c *C) {
+	// Set bucket is BucketOwner payer
+	reqPayConf := RequestPaymentConfiguration{
+		Payer:string(BucketOwner),
+	}
+
+	err := cs.client.SetBucketRequestPayment(credentialBucketName, reqPayConf)
+	c.Assert(err, IsNil)
+
+	key := objectNamePrefix + randStr(8)
+	objectValue := randStr(18)
+
+	// Put object
+	err = cs.creBucket.PutObject(key, strings.NewReader(objectValue), RequestPayer(BucketOwner))
+	c.Assert(err, IsNil)
+
+	// Put object
+	err = cs.creBucket.PutObject(key, strings.NewReader(objectValue), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Get object
+	body, err := cs.creBucket.GetObject(key, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	defer body.Close()
+
+	data, err := ioutil.ReadAll(body)
+	c.Assert(err, IsNil)
+	c.Assert(string(data), Equals, objectValue)
+
+	// List object
+	lor, err := cs.creBucket.ListObjects(RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(len(lor.Objects), Equals, 1)
+
+	err = cs.creBucket.DeleteObject(key, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+}
+
+// TestPutObjectFromFile
+func (cs *OssCredentialBucketSuite) TestPutObjectFromFile(c *C) {
+	objectName := objectNamePrefix + randStr(8)
+	localFile := "../sample/BingWallpaper-2015-11-07.jpg"
+	newFile := randStr(8) + ".jpg"
+
+	// Put
+	err := cs.creBucket.PutObjectFromFile(objectName, localFile, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Check
+	err = cs.creBucket.GetObjectToFile(objectName, newFile, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	eq, err := compareFiles(localFile, newFile)
+	c.Assert(err, IsNil)
+	c.Assert(eq, Equals, true)
+
+	meta, err := cs.creBucket.GetObjectDetailedMeta(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(meta.Get("Content-Type"), Equals, "image/jpeg")
+
+	acl, err := cs.creBucket.GetObjectACL(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("aclRes:", acl)
+	c.Assert(acl.ACL, Equals, "default")
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Put with properties
+	options := []Option{
+		Expires(futureDate),
+		ObjectACL(ACLPublicRead),
+		Meta("myprop", "mypropval"),
+		RequestPayer(Requester),
+	}
+	err = cs.creBucket.PutObjectFromFile(objectName, localFile, options...)
+	c.Assert(err, IsNil)
+
+	// Check
+	err = cs.creBucket.GetObjectToFile(objectName, newFile, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	eq, err = compareFiles(localFile, newFile)
+	c.Assert(err, IsNil)
+	c.Assert(eq, Equals, true)
+
+	acl, err = cs.creBucket.GetObjectACL(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("GetObjectACL:", acl)
+	c.Assert(acl.ACL, Equals, string(ACLPublicRead))
+
+	meta, err = cs.creBucket.GetObjectDetailedMeta(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("GetObjectDetailedMeta:", meta)
+	c.Assert(meta.Get("X-Oss-Meta-Myprop"), Equals, "mypropval")
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	os.Remove(newFile)
+}
+
+// TestCopyObject
+func (cs *OssCredentialBucketSuite) TestCopyObject(c *C) {
+	objectName := objectNamePrefix + randStr(8)
+	objectValue := randStr(18)
+
+	err := cs.creBucket.PutObject(objectName, strings.NewReader(objectValue),
+		ACL(ACLPublicRead), Meta("my", "myprop"), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Copy
+	var objectNameDest = objectName + "dest"
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Check
+	lor, err := cs.creBucket.ListObjects(Prefix(objectName), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("objects:", lor.Objects)
+	c.Assert(len(lor.Objects), Equals, 2)
+
+	body, err := cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err := readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	err = cs.creBucket.DeleteObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Copy with constraints x-oss-copy-source-if-modified-since
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, CopySourceIfModifiedSince(futureDate), RequestPayer(Requester))
+	c.Assert(err, NotNil)
+	testLogger.Println("CopyObject:", err)
+
+	// Copy with constraints x-oss-copy-source-if-unmodified-since
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, CopySourceIfUnmodifiedSince(futureDate), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Check
+	lor, err = cs.creBucket.ListObjects(Prefix(objectName), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("objects:", lor.Objects)
+	c.Assert(len(lor.Objects), Equals, 2)
+
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	err = cs.creBucket.DeleteObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Copy with constraints x-oss-copy-source-if-match
+	meta, err := cs.creBucket.GetObjectDetailedMeta(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("GetObjectDetailedMeta:", meta)
+
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, CopySourceIfMatch(meta.Get("Etag")), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Check
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	err = cs.creBucket.DeleteObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Copy with constraints x-oss-copy-source-if-none-match
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, CopySourceIfNoneMatch(meta.Get("Etag")), RequestPayer(Requester))
+	c.Assert(err, NotNil)
+
+	// Copy with constraints x-oss-metadata-directive
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, Meta("my", "mydestprop"),
+		MetadataDirective(MetaCopy), RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Check
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	destMeta, err := cs.creBucket.GetObjectDetailedMeta(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(meta.Get("X-Oss-Meta-My"), Equals, "myprop")
+
+	acl, err := cs.creBucket.GetObjectACL(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(acl.ACL, Equals, "default")
+
+	err = cs.creBucket.DeleteObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Copy with constraints x-oss-metadata-directive and self defined dest object meta
+	options := []Option{
+		ObjectACL(ACLPublicReadWrite),
+		Meta("my", "mydestprop"),
+		MetadataDirective(MetaReplace),
+		RequestPayer(Requester),
+	}
+	_, err = cs.creBucket.CopyObject(objectName, objectNameDest, options...)
+	c.Assert(err, IsNil)
+
+	// Check
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	destMeta, err = cs.creBucket.GetObjectDetailedMeta(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(destMeta.Get("X-Oss-Meta-My"), Equals, "mydestprop")
+
+	acl, err = cs.creBucket.GetObjectACL(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(acl.ACL, Equals, string(ACLPublicReadWrite))
+
+	err = cs.creBucket.DeleteObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+}
+
+// TestCopyObjectToOrFrom
+func (cs *OssCredentialBucketSuite) TestCopyObjectToOrFrom(c *C) {
+	objectName := objectNamePrefix + randStr(8)
+	objectValue := randStr(18)
+	sorBucketName := credentialBucketName + "-sor"
+	objectNameDest := objectName + "-Dest"
+
+	err := cs.client.CreateBucket(sorBucketName)
+	c.Assert(err, IsNil)
+	// Set ACL_PUBLIC_R
+	err = cs.client.SetBucketACL(sorBucketName, ACLPublicRead)
+	c.Assert(err, IsNil)
+
+	sorBucket, err := cs.client.Bucket(sorBucketName)
+	c.Assert(err, IsNil)
+
+	err = sorBucket.PutObject(objectName, strings.NewReader(objectValue))
+	c.Assert(err, IsNil)
+
+	// Copy from
+	_, err = cs.creBucket.CopyObjectFrom(sorBucketName, objectName, objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Check
+	body, err := cs.creBucket.GetObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err := readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	err = cs.creBucket.DeleteObject(objectNameDest, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Copy to
+	_, err = sorBucket.CopyObjectTo(credentialBucketName, objectName, objectName)
+	c.Assert(err, IsNil)
+
+	// Check
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	// Clean
+	err = sorBucket.DeleteObject(objectName)
+	c.Assert(err, IsNil)
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	err = cs.client.DeleteBucket(sorBucketName)
+	c.Assert(err, IsNil)
+}
+
+// TestAppendObject
+func (cs *OssCredentialBucketSuite) TestAppendObject(c *C) {
+	objectName := objectNamePrefix + randStr(8)
+	objectValue1 := randStr(18)
+	objectValue2 := randStr(18)
+	objectValue := objectValue1 + objectValue2
+	var val = []byte(objectValue)
+	var localFile = randStr(8) + ".txt"
+	var nextPos int64
+	var midPos = 1 + rand.Intn(len(val)-1)
+
+	var err = createFileAndWrite(localFile+"1", val[0:midPos])
+	c.Assert(err, IsNil)
+	err = createFileAndWrite(localFile+"2", val[midPos:])
+	c.Assert(err, IsNil)
+
+	// String append
+	nextPos, err = cs.creBucket.AppendObject(objectName, strings.NewReader(objectValue1), nextPos, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	nextPos, err = cs.creBucket.AppendObject(objectName, strings.NewReader(objectValue2), nextPos, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	body, err := cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err := readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// Byte append
+	nextPos = 0
+	nextPos, err = cs.creBucket.AppendObject(objectName, bytes.NewReader(val[0:midPos]), nextPos, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	nextPos, err = cs.creBucket.AppendObject(objectName, bytes.NewReader(val[midPos:]), nextPos, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+
+	// File append
+	options := []Option{
+		ObjectACL(ACLPublicReadWrite),
+		Meta("my", "myprop"),
+		RequestPayer(Requester),
+	}
+
+	fd, err := os.Open(localFile + "1")
+	c.Assert(err, IsNil)
+	defer fd.Close()
+	nextPos = 0
+	nextPos, err = cs.creBucket.AppendObject(objectName, fd, nextPos, options...)
+	c.Assert(err, IsNil)
+
+	meta, err := cs.creBucket.GetObjectDetailedMeta(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("GetObjectDetailedMeta:", meta, ",", nextPos)
+	c.Assert(meta.Get("X-Oss-Object-Type"), Equals, "Appendable")
+	c.Assert(meta.Get("X-Oss-Meta-My"), Equals, "myprop")
+	c.Assert(meta.Get("x-oss-Meta-Mine"), Equals, "")
+	c.Assert(meta.Get("X-Oss-Next-Append-Position"), Equals, strconv.FormatInt(nextPos, 10))
+
+	acl, err := cs.creBucket.GetObjectACL(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("GetObjectACL:", acl)
+	c.Assert(acl.ACL, Equals, string(ACLPublicReadWrite))
+
+	// Second append
+	options = []Option{
+		ObjectACL(ACLPublicRead),
+		Meta("my", "myproptwo"),
+		Meta("mine", "mypropmine"),
+		RequestPayer(Requester),
+	}
+	fd, err = os.Open(localFile + "2")
+	c.Assert(err, IsNil)
+	defer fd.Close()
+	nextPos, err = cs.creBucket.AppendObject(objectName, fd, nextPos, options...)
+	c.Assert(err, IsNil)
+
+	body, err = cs.creBucket.GetObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	str, err = readBody(body)
+	c.Assert(err, IsNil)
+	c.Assert(str, Equals, objectValue)
+
+	meta, err = cs.creBucket.GetObjectDetailedMeta(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	testLogger.Println("GetObjectDetailedMeta xxx:", meta)
+	c.Assert(meta.Get("X-Oss-Object-Type"), Equals, "Appendable")
+	c.Assert(meta.Get("X-Oss-Meta-My"), Equals, "myprop")
+	c.Assert(meta.Get("x-Oss-Meta-Mine"), Equals, "")
+	c.Assert(meta.Get("X-Oss-Next-Append-Position"), Equals, strconv.FormatInt(nextPos, 10))
+
+	acl, err = cs.creBucket.GetObjectACL(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+	c.Assert(acl.ACL, Equals, string(ACLPublicRead))
+
+	err = cs.creBucket.DeleteObject(objectName, RequestPayer(Requester))
+	c.Assert(err, IsNil)
+}

+ 61 - 0
oss/client.go

@@ -963,6 +963,67 @@ func (client Client) DeleteBucketPolicy(bucketName string, options ...Option) er
 	return checkRespCode(resp.StatusCode, []int{http.StatusNoContent})
 }
 
+// SetBucketRequestPayment API operation for Object Storage Service.
+//
+// Set the requestPayment of bucket
+//
+// bucketName the bucket name.
+//
+// paymentConfig the payment configuration
+//
+// error it's nil if no error, otherwise it's an error object.
+//
+func (client Client) SetBucketRequestPayment(bucketName string, paymentConfig RequestPaymentConfiguration, options ...Option) error {
+	params := map[string]interface{}{}
+	params["requestPayment"] = nil
+
+	var bs []byte
+	bs, err := xml.Marshal(paymentConfig)
+
+	if err != nil {
+		return err
+	}
+
+	buffer := new(bytes.Buffer)
+	buffer.Write(bs)
+
+	contentType := http.DetectContentType(buffer.Bytes())
+	headers := map[string]string{}
+	headers[HTTPHeaderContentType] = contentType
+
+	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})
+}
+
+// GetBucketRequestPayment API operation for Object Storage Service.
+//
+// Get bucket requestPayment
+//
+// bucketName the bucket name.
+//
+// RequestPaymentConfiguration the payment configuration
+//
+// error it's nil if no error, otherwise it's an error object.
+//
+func (client Client) GetBucketRequestPayment(bucketName string, options ...Option) (RequestPaymentConfiguration, error) {
+	var out RequestPaymentConfiguration
+	params := map[string]interface{}{}
+	params["requestPayment"] = nil
+
+	resp, err := client.do("GET", bucketName, params, nil, nil, options...)
+	if err != nil {
+		return out, err
+	}
+	defer resp.Body.Close()
+
+	err = xmlUnmarshal(resp.Body, &out)
+	return out, err
+}
+
 // 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

+ 51 - 0
oss/client_test.go

@@ -43,6 +43,11 @@ var (
 	stsaccessID  = os.Getenv("OSS_TEST_STS_ID")
 	stsaccessKey = os.Getenv("OSS_TEST_STS_KEY")
 	stsARN       = os.Getenv("OSS_TEST_STS_ARN")
+
+	// Credential
+	credentialAccessID   = os.Getenv("OSS_CREDENTIAL_KEY_ID")
+	credentialAccessKey  = os.Getenv("OSS_CREDENTIAL_KEY_SECRET")
+	credentialUID        = os.Getenv("OSS_CREDENTIAL_UID")
 )
 
 var (
@@ -55,6 +60,8 @@ var (
 	objectNamePrefix = "go-sdk-test-object-"
 	// sts region is one and only hangzhou
 	stsRegion = "cn-hangzhou"
+	// Credentials
+	credentialBucketName = bucketNamePrefix + randLowStr(6)
 )
 
 var (
@@ -2539,3 +2546,47 @@ func (s *OssClientSuite) TestBucketPolicyNegative(c *C) {
 
 	client.DeleteBucket(bucketName)
 }
+
+func (s *OssClientSuite) TestSetBucketRequestPayment(c *C) {
+	client, err := New(endpoint, accessID, accessKey)
+	c.Assert(err, IsNil)
+
+	bucketName := bucketNamePrefix + randLowStr(5)
+	err = client.CreateBucket(bucketName)
+	c.Assert(err, IsNil)
+
+	reqPayConf := RequestPaymentConfiguration{
+		Payer:"Requester",
+	}
+	err = client.SetBucketRequestPayment(bucketName, reqPayConf)
+	c.Assert(err, IsNil)
+
+	ret, err := client.GetBucketRequestPayment(bucketName)
+	c.Assert(err, IsNil)
+	c.Assert(ret.Payer, Equals, "Requester")
+
+	client.DeleteBucket(bucketName)
+	c.Assert(err, IsNil)
+}
+
+func (s *OssClientSuite) TestSetBucketRequestPaymentNegative(c *C) {
+	client, err := New(endpoint, accessID, accessKey)
+	c.Assert(err, IsNil)
+
+	bucketName := bucketNamePrefix + randLowStr(5)
+	err = client.CreateBucket(bucketName)
+	c.Assert(err, IsNil)
+
+	reqPayConf := RequestPaymentConfiguration{
+		Payer:"Requesterttttt",	// this is a error configuration
+	}
+	err = client.SetBucketRequestPayment(bucketName, reqPayConf)
+	c.Assert(err, NotNil)
+
+	ret, err := client.GetBucketRequestPayment(bucketName)
+	c.Assert(err, IsNil)
+	c.Assert(ret.Payer, Equals, "BucketOwner")
+
+	client.DeleteBucket(bucketName)
+	c.Assert(err, IsNil)
+}

+ 1 - 1
oss/conn.go

@@ -42,7 +42,7 @@ var signKeyList = []string{"acl", "uploads", "location", "cors",
 	"response-content-encoding", "udf", "udfName", "udfImage",
 	"udfId", "udfImageDesc", "udfApplication", "comp",
 	"udfApplicationLog", "restore", "callback", "callback-var",
-	"policy", "stat", "encryption", "versions", "versioning", "versionId"}
+	"policy", "stat", "encryption", "versions", "versioning", "versionId", "requestPayment"}
 
 // init initializes Conn
 func (conn *Conn) init(config *Config, urlMaker *urlMaker, client *http.Client) error {

+ 4 - 1
oss/const.go

@@ -79,7 +79,10 @@ type PayerType string
 
 const (
 	// Requester the requester who send the request
-	Requester PayerType = "requester"
+	Requester PayerType = "Requester"
+
+	// BucketOwner the requester who send the request
+	BucketOwner PayerType = "BucketOwner"
 )
 
 // HTTPMethod HTTP request method

+ 1 - 1
oss/option.go

@@ -206,7 +206,7 @@ func CallbackVar(callbackVar string) Option {
 
 // RequestPayer is an option to set payer who pay for the request
 func RequestPayer(payerType PayerType) Option {
-	return setHeader(HTTPHeaderOssRequester, string(payerType))
+	return setHeader(HTTPHeaderOssRequester, strings.ToLower(string(payerType)))
 }
 
 // SetTagging is an option to set object tagging

+ 6 - 0
oss/type.go

@@ -831,3 +831,9 @@ type BucketStat struct {
 	MultipartUploadCount int64    `xml:"MultipartUploadCount"`
 }
 type GetBucketStatResult BucketStat
+
+// RequestPaymentConfiguration define the request payment configuration
+type RequestPaymentConfiguration struct {
+	XMLName xml.Name `xml:"RequestPaymentConfiguration"`
+	Payer   string   `xml:"Payer,omitempty"`
+}

+ 24 - 23
sample.go

@@ -12,29 +12,30 @@ import (
 
 // sampleMap contains all samples
 var sampleMap = map[string]interface{}{
-	"CreateBucketSample":     sample.CreateBucketSample,
-	"NewBucketSample":        sample.NewBucketSample,
-	"ListBucketsSample":      sample.ListBucketsSample,
-	"BucketACLSample":        sample.BucketACLSample,
-	"BucketLifecycleSample":  sample.BucketLifecycleSample,
-	"BucketRefererSample":    sample.BucketRefererSample,
-	"BucketLoggingSample":    sample.BucketLoggingSample,
-	"BucketWebsiteSample":	  sample.BucketWebsiteSample,
-	"BucketCORSSample":       sample.BucketCORSSample,
-	"BucketPolicySample":	  sample.BucketPolicySample,
-	"ObjectACLSample":        sample.ObjectACLSample,
-	"ObjectMetaSample":       sample.ObjectMetaSample,
-	"ListObjectsSample":      sample.ListObjectsSample,
-	"DeleteObjectSample":     sample.DeleteObjectSample,
-	"AppendObjectSample":     sample.AppendObjectSample,
-	"CopyObjectSample":       sample.CopyObjectSample,
-	"PutObjectSample":        sample.PutObjectSample,
-	"GetObjectSample":        sample.GetObjectSample,
-	"CnameSample":            sample.CnameSample,
-	"SignURLSample":          sample.SignURLSample,
-	"ArchiveSample":          sample.ArchiveSample,
-	"ObjectTaggingSample":    sample.ObjectTaggingSample,
-	"BucketEncryptionSample": sample.BucketEncryptionSample,
+	"CreateBucketSample":          sample.CreateBucketSample,
+	"NewBucketSample":             sample.NewBucketSample,
+	"ListBucketsSample":           sample.ListBucketsSample,
+	"BucketACLSample":             sample.BucketACLSample,
+	"BucketLifecycleSample":       sample.BucketLifecycleSample,
+	"BucketRefererSample":         sample.BucketRefererSample,
+	"BucketLoggingSample":         sample.BucketLoggingSample,
+	"BucketWebsiteSample":	       sample.BucketWebsiteSample,
+	"BucketCORSSample":            sample.BucketCORSSample,
+	"BucketPolicySample":	       sample.BucketPolicySample,
+	"BucketrRequestPaymentSample": sample.BucketrRequestPaymentSample,
+	"ObjectACLSample":             sample.ObjectACLSample,
+	"ObjectMetaSample":            sample.ObjectMetaSample,
+	"ListObjectsSample":           sample.ListObjectsSample,
+	"DeleteObjectSample":          sample.DeleteObjectSample,
+	"AppendObjectSample":          sample.AppendObjectSample,
+	"CopyObjectSample":            sample.CopyObjectSample,
+	"PutObjectSample":             sample.PutObjectSample,
+	"GetObjectSample":             sample.GetObjectSample,
+	"CnameSample":                 sample.CnameSample,
+	"SignURLSample":               sample.SignURLSample,
+	"ArchiveSample":               sample.ArchiveSample,
+	"ObjectTaggingSample":         sample.ObjectTaggingSample,
+	"BucketEncryptionSample":      sample.BucketEncryptionSample,
 }
 
 func main() {

+ 117 - 0
sample/bucket_requestpayment.go

@@ -0,0 +1,117 @@
+package sample
+
+import (
+	"fmt"
+	"strings"
+	"io/ioutil"
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+)
+
+// BucketrRequestPaymentSample shows how to set, get the bucket request payment.
+func BucketrRequestPaymentSample() {
+	// 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)
+	}
+
+	reqPayConf := oss.RequestPaymentConfiguration{
+		Payer: string(oss.Requester),
+	}
+
+	// Case 1: Set bucket request payment.
+	err = client.SetBucketRequestPayment(bucketName, reqPayConf)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Get bucket request payment configuration
+	ret, err := client.GetBucketRequestPayment(bucketName)
+	if err != nil {
+		HandleError(err)
+	}
+	fmt.Println("Bucket request payer:", ret.Payer)
+
+	if credentialUID == "" {
+		fmt.Println("Please enter a credential User ID, if you want to test credential user.")
+		clearData(client, bucketName)
+		return
+	}
+	// Credential other User
+	policyInfo := `
+	{
+		"Version":"1",
+		"Statement":[
+			{
+				"Action":[
+					"oss:*"
+				],
+				"Effect":"Allow",
+				"Principal":["` + credentialUID + `"],
+				"Resource":["acs:oss:*:*:` + bucketName + `", "acs:oss:*:*:` + bucketName + `/*"]
+			}
+		]
+	}`
+
+	err = client.SetBucketPolicy(bucketName, policyInfo)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// New a Credential client
+	creClient, err := oss.New(endpoint, credentialAccessID, credentialAccessKey)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Get credential bucket
+	creBucket, err := creClient.Bucket(bucketName)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Put object by credential User
+	key := "testCredentialObject"
+	objectValue := "this is a test string."
+	// Put object
+	err = creBucket.PutObject(key, strings.NewReader(objectValue), oss.RequestPayer(oss.Requester))
+	if err != nil {
+		HandleError(err)
+	}
+	// Get object
+	body, err := creBucket.GetObject(key, oss.RequestPayer(oss.Requester))
+	if err != nil {
+		HandleError(err)
+	}
+	defer body.Close()
+
+	data, err := ioutil.ReadAll(body)
+	if err != nil {
+		HandleError(err)
+	}
+	fmt.Println(string(data))
+	
+	// Delete object
+	err = creBucket.DeleteObject(key, oss.RequestPayer(oss.Requester))
+	if err != nil {
+		HandleError(err)
+	}
+
+	clearData(client, bucketName)
+}
+
+func clearData(client *oss.Client, bucketName string) {
+	// Delete bucket
+	err := client.DeleteBucket(bucketName)
+	if err != nil {
+		HandleError(err)
+	}
+
+	fmt.Println("BucketrRequestPaymentSample completed")
+}

+ 5 - 0
sample/config.go

@@ -10,6 +10,11 @@ var (
 	bucketName = os.Getenv("OSS_TEST_BUCKET")
 	kmsID      = os.Getenv("OSS_TEST_KMS_ID")
 
+	// Credential
+	credentialAccessID  = os.Getenv("OSS_CREDENTIAL_KEY_ID")
+	credentialAccessKey = os.Getenv("OSS_CREDENTIAL_KEY_SECRET")
+	credentialUID       = os.Getenv("OSS_CREDENTIAL_UID")
+
 	// The cname endpoint
 	endpoint4Cname = os.Getenv("OSS_TEST_CNAME_ENDPOINT")
 )