Skip to content

Commit

Permalink
add for versioning && bucket tagging && bucket encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
taowei.wtw committed May 21, 2019
1 parent b233b40 commit e02c7c7
Show file tree
Hide file tree
Showing 21 changed files with 2,804 additions and 178 deletions.
12 changes: 7 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ install:
- if [[ $TRAVIS_GO_VERSION = '1.7' || $TRAVIS_GO_VERSION > '1.7' ]]; then go get golang.org/x/time/rate
; fi
script:
- if [ -n "$OSS_TEST_ACCESS_KEY_ID" ]; then
cd oss;
travis_wait 30 go test -v -covermode=count -coverprofile=coverage.out -timeout=30m;
$HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci;
fi
- if [[ ! -n "$OSS_TEST_ACCESS_KEY_ID" ]]; then exit 0
; fi

- cd oss
- travis_wait 30 go test -v -covermode=count -coverprofile=coverage.out -timeout=30m
- "$HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci"

env:
global:
- secure: ZCL5egxJmZA+o1ujsaJe//AIh1ag/exSUJ2FzoKPF3O9c84hMc2k5EYO2rGzTNn1ML6M89Mo5hAvHQhyJEHjRuMtjc1QrfxAaA3mqm4scGXIXesPMqYGuvuPSh++6/fkAwaVBAhrk5GaDG1/FuxHE5zusGx3SvGegnCwO7n/2YCfXco6DWgVCdrz4p1EpPkAM3JIdHFUzsDWiimVuiNAvJmAT8+IeOPTT+WgusCJj4ORS3X3LddTjttBP+hRrp/pGSoNqPMzfysWybtaL2SJ8URtvsxW0Mo5BwocHAxAhPP+M2OscQbDzthSAezCLngYvrfBplfIyWlahlgzNz/FjXz5pQwWdYVNoibyxLLMOH685n75LNONN/xVO/GFmVPx7DMGapkN5NzIWS62D4v8QrRkwtms42OUkyEUHjDh8Evui3K2MNJVXA3TI9zOAR+C0krD7OEyS37qrppodhRxJSqFUlgXnk//wLldMC7vleDd7L2UQSWjqyBHqFOgsVaiLU2KRTY3zvv7ke+dqb5VF31mH6qAr8lJTR9un8M1att0VwCEKxoIRT4cKJCpEtZd8ovXOVt1uE695ThVXE9I5e00GXdTzqXOuv6zT4hv/dgmbz9JN9MYeCwmokEoIUmJKNYERa/bNVVefdnJt7h+dm+KpyPAS+XvPLzjbnWdYNA=
Expand Down
207 changes: 173 additions & 34 deletions oss/bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,17 @@ func (bucket Bucket) DoGetObject(request *GetObjectRequest, options []Option) (*
//
func (bucket Bucket) CopyObject(srcObjectKey, destObjectKey string, options ...Option) (CopyObjectResult, error) {
var out CopyObjectResult
options = append(options, CopySource(bucket.BucketName, url.QueryEscape(srcObjectKey)))

//first find version id
versionIdKey := "versionId"
versionId, _ := findOption(options, versionIdKey, nil)
if versionId == nil {
options = append(options, CopySource(bucket.BucketName, url.QueryEscape(srcObjectKey)))
} else {
options = deleteOption(options, versionIdKey)
options = append(options, CopySourceVersion(bucket.BucketName, url.QueryEscape(srcObjectKey), versionId.(string)))
}

params := map[string]interface{}{}
resp, err := bucket.do("PUT", destObjectKey, params, options, nil, nil)
if err != nil {
Expand Down Expand Up @@ -281,14 +291,32 @@ func (bucket Bucket) CopyObjectFrom(srcBucketName, srcObjectKey, destObjectKey s

func (bucket Bucket) copy(srcObjectKey, destBucketName, destObjectKey string, options ...Option) (CopyObjectResult, error) {
var out CopyObjectResult
options = append(options, CopySource(bucket.BucketName, url.QueryEscape(srcObjectKey)))

//first find version id
versionIdKey := "versionId"
versionId, _ := findOption(options, versionIdKey, nil)
if versionId == nil {
options = append(options, CopySource(bucket.BucketName, url.QueryEscape(srcObjectKey)))
} else {
options = deleteOption(options, versionIdKey)
options = append(options, CopySourceVersion(bucket.BucketName, url.QueryEscape(srcObjectKey), versionId.(string)))
}

headers := make(map[string]string)
err := handleOptions(headers, options)
if err != nil {
return out, err
}
params := map[string]interface{}{}
resp, err := bucket.Client.Conn.Do("PUT", destBucketName, destObjectKey, params, headers, nil, 0, nil)

// get response header
respHeader, _ := findOption(options, responseHeader, nil)
if respHeader != nil {
pRespHeader := respHeader.(*http.Header)
*pRespHeader = resp.Headers
}

if err != nil {
return out, err
}
Expand Down Expand Up @@ -357,6 +385,14 @@ func (bucket Bucket) DoAppendObject(request *AppendObjectRequest, options []Opti
handleOptions(headers, opts)
resp, err := bucket.Client.Conn.Do("POST", bucket.BucketName, request.ObjectKey, params, headers,
request.Reader, initCRC, listener)

// get response header
respHeader, _ := findOption(options, responseHeader, nil)
if respHeader != nil {
pRespHeader := respHeader.(*http.Header)
*pRespHeader = resp.Headers
}

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -384,9 +420,9 @@ func (bucket Bucket) DoAppendObject(request *AppendObjectRequest, options []Opti
//
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) DeleteObject(objectKey string) error {
params := map[string]interface{}{}
resp, err := bucket.do("DELETE", objectKey, params, nil, nil, nil)
func (bucket Bucket) DeleteObject(objectKey string, options ...Option) error {
params, _ := getRawParams(options)
resp, err := bucket.do("DELETE", objectKey, params, options, nil, nil)
if err != nil {
return err
}
Expand All @@ -409,6 +445,63 @@ func (bucket Bucket) DeleteObjects(objectKeys []string, options ...Option) (Dele
for _, key := range objectKeys {
dxml.Objects = append(dxml.Objects, DeleteObject{Key: key})
}

isQuiet, _ := findOption(options, deleteObjectsQuiet, false)
dxml.Quiet = isQuiet.(bool)

bs, err := xml.Marshal(dxml)
if err != nil {
return out, err
}
buffer := new(bytes.Buffer)
buffer.Write(bs)

contentType := http.DetectContentType(buffer.Bytes())
options = append(options, ContentType(contentType))
sum := md5.Sum(bs)
b64 := base64.StdEncoding.EncodeToString(sum[:])
options = append(options, ContentMD5(b64))

params := map[string]interface{}{}
params["delete"] = nil
params["encoding-type"] = "url"

resp, err := bucket.do("POST", "", params, options, buffer, nil)
if err != nil {
return out, err
}
defer resp.Body.Close()

deletedResult := DeleteObjectVersionsResult{}
if !dxml.Quiet {
if err = xmlUnmarshal(resp.Body, &deletedResult); err == nil {
err = decodeDeleteObjectsResult(&deletedResult)
}
}

// Keep compatibility:need convert to struct DeleteObjectsResult
out.XMLName = deletedResult.XMLName
for _, v := range deletedResult.DeletedObjectsDetail {
out.DeletedObjects = append(out.DeletedObjects, v.Key)
}

return out, err
}

// DeleteObjectVersions deletes multiple object versions.
//
// objectVersions the object keys and versions to delete.
// options the options for deleting objects.
// Supported option is DeleteObjectsQuiet which means it will not return error even deletion failed (not recommended). By default it's not used.
//
// DeleteObjectVersionsResult the result object.
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) DeleteObjectVersions(objectVersions []DeleteObject, options ...Option) (DeleteObjectVersionsResult, error) {
out := DeleteObjectVersionsResult{}
dxml := deleteXML{}
dxml.Objects = objectVersions

isQuiet, _ := findOption(options, deleteObjectsQuiet, false)
dxml.Quiet = isQuiet.(bool)

Expand Down Expand Up @@ -509,6 +602,32 @@ func (bucket Bucket) ListObjects(options ...Option) (ListObjectsResult, error) {
return out, err
}

// ListObjectVersions lists objects of all versions under the current bucket.
func (bucket Bucket) ListObjectVersions(options ...Option) (ListObjectVersionsResult, error) {
var out ListObjectVersionsResult

options = append(options, EncodingType("url"))
params, err := getRawParams(options)
if err != nil {
return out, err
}
params["versions"] = nil

resp, err := bucket.do("GET", "", params, options, nil, nil)
if err != nil {
return out, err
}
defer resp.Body.Close()

err = xmlUnmarshal(resp.Body, &out)
if err != nil {
return out, err
}

err = decodeListObjectVersionsResult(&out)
return out, err
}

// SetObjectMeta sets the metadata of the Object.
//
// objectKey object
Expand All @@ -533,7 +652,7 @@ func (bucket Bucket) SetObjectMeta(objectKey string, options ...Option) error {
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) GetObjectDetailedMeta(objectKey string, options ...Option) (http.Header, error) {
params := map[string]interface{}{}
params, _ := getRawParams(options)
resp, err := bucket.do("HEAD", objectKey, params, options, nil, nil)
if err != nil {
return nil, err
Expand All @@ -554,7 +673,7 @@ func (bucket Bucket) GetObjectDetailedMeta(objectKey string, options ...Option)
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) GetObjectMeta(objectKey string, options ...Option) (http.Header, error) {
params := map[string]interface{}{}
params, _ := getRawParams(options)
params["objectMeta"] = nil
//resp, err := bucket.do("GET", objectKey, "?objectMeta", "", nil, nil, nil)
resp, err := bucket.do("HEAD", objectKey, params, options, nil, nil)
Expand Down Expand Up @@ -582,9 +701,9 @@ func (bucket Bucket) GetObjectMeta(objectKey string, options ...Option) (http.He
//
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) SetObjectACL(objectKey string, objectACL ACLType) error {
options := []Option{ObjectACL(objectACL)}
params := map[string]interface{}{}
func (bucket Bucket) SetObjectACL(objectKey string, objectACL ACLType, options ...Option) error {
options = append(options, ObjectACL(objectACL))
params, _ := getRawParams(options)
params["acl"] = nil
resp, err := bucket.do("PUT", objectKey, params, options, nil, nil)
if err != nil {
Expand All @@ -601,11 +720,11 @@ func (bucket Bucket) SetObjectACL(objectKey string, objectACL ACLType) error {
// GetObjectACLResult the result object when error is nil. GetObjectACLResult.Acl is the object ACL.
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) GetObjectACL(objectKey string) (GetObjectACLResult, error) {
func (bucket Bucket) GetObjectACL(objectKey string, options ...Option) (GetObjectACLResult, error) {
var out GetObjectACLResult
params := map[string]interface{}{}
params, _ := getRawParams(options)
params["acl"] = nil
resp, err := bucket.do("GET", objectKey, params, nil, nil, nil)
resp, err := bucket.do("GET", objectKey, params, options, nil, nil)
if err != nil {
return out, err
}
Expand All @@ -630,7 +749,7 @@ func (bucket Bucket) GetObjectACL(objectKey string) (GetObjectACLResult, error)
//
func (bucket Bucket) PutSymlink(symObjectKey string, targetObjectKey string, options ...Option) error {
options = append(options, symlinkTarget(url.QueryEscape(targetObjectKey)))
params := map[string]interface{}{}
params, _ := getRawParams(options)
params["symlink"] = nil
resp, err := bucket.do("PUT", symObjectKey, params, options, nil, nil)
if err != nil {
Expand All @@ -648,10 +767,10 @@ func (bucket Bucket) PutSymlink(symObjectKey string, targetObjectKey string, opt
// error it's nil if no error, otherwise it's an error object.
// When error is nil, the target file key is in the X-Oss-Symlink-Target header of the returned object.
//
func (bucket Bucket) GetSymlink(objectKey string) (http.Header, error) {
params := map[string]interface{}{}
func (bucket Bucket) GetSymlink(objectKey string, options ...Option) (http.Header, error) {
params, _ := getRawParams(options)
params["symlink"] = nil
resp, err := bucket.do("GET", objectKey, params, nil, nil, nil)
resp, err := bucket.do("GET", objectKey, params, options, nil, nil)
if err != nil {
return nil, err
}
Expand All @@ -678,10 +797,10 @@ func (bucket Bucket) GetSymlink(objectKey string) (http.Header, error) {
//
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) RestoreObject(objectKey string) error {
params := map[string]interface{}{}
func (bucket Bucket) RestoreObject(objectKey string, options ...Option) error {
params, _ := getRawParams(options)
params["restore"] = nil
resp, err := bucket.do("POST", objectKey, params, nil, nil, nil)
resp, err := bucket.do("POST", objectKey, params, options, nil, nil)
if err != nil {
return err
}
Expand Down Expand Up @@ -911,9 +1030,9 @@ func (bucket Bucket) DoGetObjectWithURL(signedURL string, options []Option) (*Ge
//
// error it's nil if no error, otherwise it's an error object.
//
func (bucket Bucket) ProcessObject(objectKey string, process string) (ProcessObjectResult, error) {
func (bucket Bucket) ProcessObject(objectKey string, process string, options ...Option) (ProcessObjectResult, error) {
var out ProcessObjectResult
params := map[string]interface{}{}
params, _ := getRawParams(options)
params["x-oss-process"] = nil
processData := fmt.Sprintf("%v=%v", "x-oss-process", process)
data := strings.NewReader(processData)
Expand All @@ -935,7 +1054,7 @@ func (bucket Bucket) ProcessObject(objectKey string, process string) (ProcessObj
//
// error nil if success, otherwise error
//
func (bucket Bucket) PutObjectTagging(objectKey string, tagging ObjectTagging) error {
func (bucket Bucket) PutObjectTagging(objectKey string, tagging Tagging, options ...Option) error {
bs, err := xml.Marshal(tagging)
if err != nil {
return err
Expand All @@ -944,9 +1063,9 @@ func (bucket Bucket) PutObjectTagging(objectKey string, tagging ObjectTagging) e
buffer := new(bytes.Buffer)
buffer.Write(bs)

params := map[string]interface{}{}
params, _ := getRawParams(options)
params["tagging"] = nil
resp, err := bucket.do("PUT", objectKey, params, nil, buffer, nil)
resp, err := bucket.do("PUT", objectKey, params, options, buffer, nil)
if err != nil {
return err
}
Expand All @@ -963,12 +1082,12 @@ func (bucket Bucket) PutObjectTagging(objectKey string, tagging ObjectTagging) e
// Tagging
// error nil if success, otherwise error
//
func (bucket Bucket) GetObjectTagging(objectKey string) (ObjectTagging, error) {
var out ObjectTagging
params := map[string]interface{}{}
func (bucket Bucket) GetObjectTagging(objectKey string, options ...Option) (GetObjectTaggingResult, error) {
var out GetObjectTaggingResult
params, _ := getRawParams(options)
params["tagging"] = nil

resp, err := bucket.do("GET", objectKey, params, nil, nil, nil)
resp, err := bucket.do("GET", objectKey, params, options, nil, nil)
if err != nil {
return out, err
}
Expand All @@ -985,15 +1104,15 @@ func (bucket Bucket) GetObjectTagging(objectKey string) (ObjectTagging, error) {
//
// error nil if success, otherwise error
//
func (bucket Bucket) DeleteObjectTagging(objectKey string) error {
params := map[string]interface{}{}
func (bucket Bucket) DeleteObjectTagging(objectKey string, options ...Option) error {
params, _ := getRawParams(options)
params["tagging"] = nil

if objectKey == "" {
return fmt.Errorf("invalid argument: object name is empty")
}

resp, err := bucket.do("DELETE", objectKey, params, nil, nil, nil)
resp, err := bucket.do("DELETE", objectKey, params, options, nil, nil)
if err != nil {
return err
}
Expand All @@ -1010,8 +1129,18 @@ func (bucket Bucket) do(method, objectName string, params map[string]interface{}
if err != nil {
return nil, err
}
return bucket.Client.Conn.Do(method, bucket.BucketName, objectName,

resp, err := bucket.Client.Conn.Do(method, bucket.BucketName, objectName,
params, headers, data, 0, listener)

// get response header
respHeader, _ := findOption(options, responseHeader, nil)
if respHeader != nil {
pRespHeader := respHeader.(*http.Header)
*pRespHeader = resp.Headers
}

return resp, err
}

func (bucket Bucket) doURL(method HTTPMethod, signedURL string, params map[string]interface{}, options []Option,
Expand All @@ -1021,7 +1150,17 @@ func (bucket Bucket) doURL(method HTTPMethod, signedURL string, params map[strin
if err != nil {
return nil, err
}
return bucket.Client.Conn.DoURL(method, signedURL, headers, data, 0, listener)

resp, err := bucket.Client.Conn.DoURL(method, signedURL, headers, data, 0, listener)

// get response header
respHeader, _ := findOption(options, responseHeader, nil)
if respHeader != nil {
pRespHeader := respHeader.(*http.Header)
*pRespHeader = resp.Headers
}

return resp, err
}

func (bucket Bucket) getConfig() *Config {
Expand Down
Loading

0 comments on commit e02c7c7

Please sign in to comment.