Skip to content

Commit

Permalink
Merge pull request #210 from tencentyun/feature_jojoliang_545270c7
Browse files Browse the repository at this point in the history
add getPresignedURL2
  • Loading branch information
agin719 authored Oct 9, 2023
2 parents f71fa88 + dafc973 commit 625550d
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 1 deletion.
2 changes: 1 addition & 1 deletion cos.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (

const (
// Version current go sdk version
Version = "0.7.43"
Version = "0.7.44"
UserAgent = "cos-go-sdk-v5/" + Version
contentTypeXML = "application/xml"
defaultServiceBaseURL = "http://service.cos.myqcloud.com"
Expand Down
49 changes: 49 additions & 0 deletions example/object/getByPresignedURL2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"context"
"fmt"
"github.com/tencentyun/cos-go-sdk-v5"
"net/http"
"net/url"
"os"
"strings"
"time"
)

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{
// 通过环境变量获取密钥
// 环境变量 COS_SECRETID 表示用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capi
SecretID: os.Getenv("COS_SECRETID"),
// 环境变量 COS_SECRETKEY 表示用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capi
SecretKey: os.Getenv("COS_SECRETKEY"),
SessionToken: "<token>", // 请替换成您的临时密钥
},
})

name := "exampleobject"
ctx := context.Background()

// 获取预签名
presignedURL, err := c.Object.GetPresignedURL2(ctx, http.MethodPut, name, time.Hour, nil)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("url: %v\n", presignedURL.String())
// 通过预签名方式上传对象
data := "test upload with presignedURL"
f := strings.NewReader(data)
req, err := http.NewRequest(http.MethodPut, presignedURL.String(), f)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
_, err = http.DefaultClient.Do(req)
if err != nil {
fmt.Printf("Error: %v\n", err)
}
}
75 changes: 75 additions & 0 deletions object.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,81 @@ func (s *ObjectService) GetPresignedURL(ctx context.Context, httpMethod, name, a
return req.URL, nil
}

func (s *ObjectService) GetPresignedURL2(ctx context.Context, httpMethod, name string, expired time.Duration, opt interface{}, signHost ...bool) (*url.URL, error) {
// 兼容 name 以 / 开头的情况
if strings.HasPrefix(name, "/") {
name = encodeURIComponent("/") + encodeURIComponent(name[1:], []byte{'/'})
} else {
name = encodeURIComponent(name, []byte{'/'})
}

cred := s.client.GetCredential()
if cred == nil {
return nil, fmt.Errorf("GetCredential failed")
}
sendOpt := sendOptions{
baseURL: s.client.BaseURL.BucketURL,
uri: "/" + name,
method: httpMethod,
optQuery: opt,
optHeader: opt,
}
mark := "?"
if popt, ok := opt.(*PresignedURLOptions); ok {
if popt != nil && popt.Query != nil {
qs := popt.Query.Encode()
if qs != "" {
sendOpt.uri = fmt.Sprintf("%s?%s", sendOpt.uri, qs)
mark = "&"
}
}
}
if cred.SessionToken != "" {
sendOpt.uri = fmt.Sprintf("%s%s%s", sendOpt.uri, mark, url.Values{"x-cos-security-token": []string{cred.SessionToken}}.Encode())
}

req, err := s.client.newRequest(ctx, sendOpt.baseURL, sendOpt.uri, sendOpt.method, sendOpt.body, sendOpt.optQuery, sendOpt.optHeader)
if err != nil {
return nil, err
}

var authTime *AuthTime
if opt != nil {
if opt, ok := opt.(*presignedURLTestingOptions); ok {
authTime = opt.authTime
}
}
if authTime == nil {
authTime = NewAuthTime(expired)
}
signedHost := true
if len(signHost) > 0 {
signedHost = signHost[0]
}
authorization := newAuthorization(cred.SecretID, cred.SecretKey, req, authTime, signedHost)
if opt != nil {
if opt, ok := opt.(*PresignedURLOptions); ok {
if opt.SignMerged {
sign := encodeURIComponent(authorization)
if req.URL.RawQuery == "" {
req.URL.RawQuery = fmt.Sprintf("sign=%s", sign)
} else {
req.URL.RawQuery = fmt.Sprintf("%s&sign=%s", req.URL.RawQuery, sign)
}
return req.URL, nil
}
}
}
sign := encodeURIComponent(authorization, []byte{'&', '='})

if req.URL.RawQuery == "" {
req.URL.RawQuery = fmt.Sprintf("%s", sign)
} else {
req.URL.RawQuery = fmt.Sprintf("%s&%s", req.URL.RawQuery, sign)
}
return req.URL, nil
}

func (s *ObjectService) GetSignature(ctx context.Context, httpMethod, name, ak, sk string, expired time.Duration, opt *PresignedURLOptions, signHost ...bool) string {
// 兼容 name 以 / 开头的情况
if strings.HasPrefix(name, "/") {
Expand Down
43 changes: 43 additions & 0 deletions object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,49 @@ func TestObjectService_GetPresignedURL(t *testing.T) {
}
}

func TestObjectService_GetPresignedURL2(t *testing.T) {
setup()
defer teardown()

u, _ := url.Parse(server.URL)
client := NewClient(&BaseURL{u, u, u, u, u}, &http.Client{
Transport: &AuthorizationTransport{
SecretID: "QmFzZTY0IGlzIGEgZ*******",
SecretKey: "ZfbOA78asKUYBcXFrJD0a1I*******",
},
})

exceptSign := "q-sign-algorithm=sha1&q-ak=QmFzZTY0IGlzIGEgZ*******&q-sign-time=1622702557;1622706157&q-key-time=1622702557;1622706157&q-header-list=&q-url-param-list=&q-signature=0f359fe9d29e7fa0c738ce6c8feaf4ed1e84f287"
exceptURL := &url.URL{
Scheme: "http",
Host: client.Host,
Path: "/test.jpg",
RawQuery: exceptSign,
}

c := context.Background()
name := "test.jpg"
startTime := time.Unix(int64(1622702557), 0)
endTime := time.Unix(int64(1622706157), 0)
opt := presignedURLTestingOptions{
authTime: &AuthTime{
SignStartTime: startTime,
SignEndTime: endTime,
KeyStartTime: startTime,
KeyEndTime: endTime,
},
}

presignedURL, err := client.Object.GetPresignedURL2(c, http.MethodPut, name, time.Hour, opt)
if err != nil {
t.Fatal(err)
}

if reflect.DeepEqual(exceptURL, presignedURL) {
t.Fatalf("Wrong PreSignedURL!")
}
}

func TestObjectService_Put(t *testing.T) {
setup()
defer teardown()
Expand Down

0 comments on commit 625550d

Please sign in to comment.