Skip to content

Commit 40f4c02

Browse files
authored
Merge pull request #234 from tencentyun/feature_jojoliang_9a5a6c47
更新ACL常量,兼容key非法时分块上传返回xml解析失败
2 parents 1c9f083 + 543e658 commit 40f4c02

File tree

3 files changed

+105
-3
lines changed

3 files changed

+105
-3
lines changed

cos.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,26 @@ type ACLXml struct {
569569
AccessControlList []ACLGrant `xml:"AccessControlList>Grant,omitempty"`
570570
}
571571

572+
type aclEnum struct {
573+
Private string
574+
PublicRead string
575+
PublicReadWrite string
576+
AuthenticatedRead string
577+
Default string
578+
BucketOwnerRead string
579+
BucketOwnerFullControl string
580+
}
581+
582+
var ACL = &aclEnum{
583+
Private: "private",
584+
PublicRead: "public-read",
585+
PublicReadWrite: "public-read-write",
586+
AuthenticatedRead: "authenticated-read",
587+
Default: "default",
588+
BucketOwnerRead: "bucket-owner-read",
589+
BucketOwnerFullControl: "bucket-owner-full-control",
590+
}
591+
572592
func decodeACL(resp *Response, res *ACLXml) {
573593
ItemMap := map[string]string{
574594
"ACL": "x-cos-acl",

helper.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net/http"
1313
"net/url"
1414
"os"
15+
"regexp"
1516
"strconv"
1617
"strings"
1718
)
@@ -394,3 +395,62 @@ func deliverInitOptions(opt *InitiateMultipartUploadOptions) (*http.Header, erro
394395
}
395396
return header, nil
396397
}
398+
399+
var (
400+
bucketReg = regexp.MustCompile(`<Bucket>([a-z0-9-]+-[0-9]+)</Bucket>`)
401+
keyReg = regexp.MustCompile(`<Key>(.*?)</Key>`)
402+
uploadIdReg = regexp.MustCompile(`<UploadId>([a-z0-9]+)</UploadId>`)
403+
locationReg = regexp.MustCompile(`<Location>(.*?)</Location>`)
404+
etagReg = regexp.MustCompile(`<ETag>&quot;(.*?)&quot;</ETag>`)
405+
)
406+
407+
func UnmarshalInitMultiUploadResult(data []byte, res *InitiateMultipartUploadResult) error {
408+
match := bucketReg.FindStringSubmatch(string(data))
409+
if len(match) > 1 {
410+
res.Bucket = match[1]
411+
} else {
412+
return fmt.Errorf("Unmarshal failed, %v", string(data))
413+
}
414+
match = keyReg.FindStringSubmatch(string(data))
415+
if len(match) > 1 {
416+
res.Key = match[1]
417+
} else {
418+
return fmt.Errorf("Unmarshal failed, %v", string(data))
419+
}
420+
match = uploadIdReg.FindStringSubmatch(string(data))
421+
if len(match) > 1 {
422+
res.UploadID = match[1]
423+
} else {
424+
return fmt.Errorf("Unmarshal failed, %v", string(data))
425+
}
426+
return nil
427+
}
428+
429+
func UnmarshalCompleteMultiUploadResult(data []byte, res *CompleteMultipartUploadResult) error {
430+
match := locationReg.FindStringSubmatch(string(data))
431+
if len(match) > 1 {
432+
res.Location = match[1]
433+
} else {
434+
return fmt.Errorf("Unmarshal failed, %v", string(data))
435+
}
436+
match = bucketReg.FindStringSubmatch(string(data))
437+
if len(match) > 1 {
438+
res.Bucket = match[1]
439+
} else {
440+
return fmt.Errorf("Unmarshal failed, %v", string(data))
441+
}
442+
match = keyReg.FindStringSubmatch(string(data))
443+
if len(match) > 1 {
444+
res.Key = match[1]
445+
} else {
446+
return fmt.Errorf("Unmarshal failed, %v", string(data))
447+
}
448+
match = etagReg.FindStringSubmatch(string(data))
449+
if len(match) > 1 {
450+
res.ETag = "\"" + match[1] + "\""
451+
} else {
452+
return fmt.Errorf("Unmarshal failed, %v", string(data))
453+
}
454+
455+
return nil
456+
}

object_part.go

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,26 @@ type InitiateMultipartUploadResult struct {
3333
//
3434
// https://www.qcloud.com/document/product/436/7746
3535
func (s *ObjectService) InitiateMultipartUpload(ctx context.Context, name string, opt *InitiateMultipartUploadOptions) (*InitiateMultipartUploadResult, *Response, error) {
36+
var buff bytes.Buffer
3637
var res InitiateMultipartUploadResult
3738
sendOpt := sendOptions{
3839
baseURL: s.client.BaseURL.BucketURL,
3940
uri: "/" + encodeURIComponent(name) + "?uploads",
4041
method: http.MethodPost,
4142
optHeader: opt,
42-
result: &res,
43+
result: &buff,
4344
}
4445
resp, err := s.client.doRetry(ctx, &sendOpt)
46+
if err == nil {
47+
err = xml.Unmarshal(buff.Bytes(), &res)
48+
if err != nil {
49+
// xml body存在非法字符(key存在非法字符)
50+
if _, ok := err.(*xml.SyntaxError); ok {
51+
err = UnmarshalInitMultiUploadResult(buff.Bytes(), &res)
52+
return &res, resp, err
53+
}
54+
}
55+
}
4556
return &res, resp, err
4657
}
4758

@@ -233,20 +244,31 @@ func (o ObjectList) Less(i, j int) bool { // rewrite the Less method from small
233244
// https://www.qcloud.com/document/product/436/7742
234245
func (s *ObjectService) CompleteMultipartUpload(ctx context.Context, name, uploadID string, opt *CompleteMultipartUploadOptions) (*CompleteMultipartUploadResult, *Response, error) {
235246
u := fmt.Sprintf("/%s?uploadId=%s", encodeURIComponent(name), uploadID)
247+
var buff bytes.Buffer
236248
var res CompleteMultipartUploadResult
237249
sendOpt := sendOptions{
238250
baseURL: s.client.BaseURL.BucketURL,
239251
uri: u,
240252
method: http.MethodPost,
241253
optHeader: opt,
242254
body: opt,
243-
result: &res,
255+
result: &buff,
244256
}
245257
resp, err := s.client.doRetry(ctx, &sendOpt)
246258
// If the error occurs during the copy operation, the error response is embedded in the 200 OK response. This means that a 200 OK response can contain either a success or an error.
247259
if err == nil && resp.StatusCode == 200 {
260+
err = xml.Unmarshal(buff.Bytes(), &res)
261+
if err != nil {
262+
// xml body存在非法字符(key存在非法字符)
263+
if _, ok := err.(*xml.SyntaxError); ok {
264+
err = UnmarshalCompleteMultiUploadResult(buff.Bytes(), &res)
265+
if err != nil {
266+
return &res, resp, err
267+
}
268+
}
269+
}
248270
if res.ETag == "" {
249-
return &res, resp, errors.New("response 200 OK, but body contains an error")
271+
return &res, resp, fmt.Errorf("response 200 OK, but body contains an error, %v", buff.Bytes())
250272
}
251273
}
252274
return &res, resp, err

0 commit comments

Comments
 (0)