github.com/aliyun/aliyun-oss-go-sdk@v3.0.2+incompatible/oss/conn_test.go (about)

     1  package oss
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"os"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	. "gopkg.in/check.v1"
    13  )
    14  
    15  type OssConnSuite struct{}
    16  
    17  var _ = Suite(&OssConnSuite{})
    18  
    19  func (s *OssConnSuite) TestURLMarker(c *C) {
    20  	um := urlMaker{}
    21  	um.Init("docs.github.com", true, false)
    22  	c.Assert(um.Type, Equals, urlTypeCname)
    23  	c.Assert(um.Scheme, Equals, "http")
    24  	c.Assert(um.NetLoc, Equals, "docs.github.com")
    25  
    26  	c.Assert(um.getURL("bucket", "object", "params").String(), Equals, "http://docs.github.com/object?params")
    27  	c.Assert(um.getURL("bucket", "object", "").String(), Equals, "http://docs.github.com/object")
    28  	c.Assert(um.getURL("", "object", "").String(), Equals, "http://docs.github.com/object")
    29  
    30  	var conn Conn
    31  	conn.config = getDefaultOssConfig()
    32  	conn.config.AuthVersion = AuthV1
    33  	c.Assert(conn.getResource("bucket", "object", "subres"), Equals, "/bucket/object?subres")
    34  	c.Assert(conn.getResource("bucket", "object", ""), Equals, "/bucket/object")
    35  	c.Assert(conn.getResource("", "object", ""), Equals, "/")
    36  
    37  	um.Init("https://docs.github.com", true, false)
    38  	c.Assert(um.Type, Equals, urlTypeCname)
    39  	c.Assert(um.Scheme, Equals, "https")
    40  	c.Assert(um.NetLoc, Equals, "docs.github.com")
    41  
    42  	um.Init("http://docs.github.com", true, false)
    43  	c.Assert(um.Type, Equals, urlTypeCname)
    44  	c.Assert(um.Scheme, Equals, "http")
    45  	c.Assert(um.NetLoc, Equals, "docs.github.com")
    46  
    47  	um.Init("docs.github.com:8080", false, true)
    48  	c.Assert(um.Type, Equals, urlTypeAliyun)
    49  	c.Assert(um.Scheme, Equals, "http")
    50  	c.Assert(um.NetLoc, Equals, "docs.github.com:8080")
    51  
    52  	c.Assert(um.getURL("bucket", "object", "params").String(), Equals, "http://bucket.docs.github.com:8080/object?params")
    53  	c.Assert(um.getURL("bucket", "object", "").String(), Equals, "http://bucket.docs.github.com:8080/object")
    54  	c.Assert(um.getURL("", "object", "").String(), Equals, "http://docs.github.com:8080/")
    55  	c.Assert(conn.getResource("bucket", "object", "subres"), Equals, "/bucket/object?subres")
    56  	c.Assert(conn.getResource("bucket", "object", ""), Equals, "/bucket/object")
    57  	c.Assert(conn.getResource("", "object", ""), Equals, "/")
    58  
    59  	um.Init("https://docs.github.com:8080", false, true)
    60  	c.Assert(um.Type, Equals, urlTypeAliyun)
    61  	c.Assert(um.Scheme, Equals, "https")
    62  	c.Assert(um.NetLoc, Equals, "docs.github.com:8080")
    63  
    64  	um.Init("127.0.0.1", false, true)
    65  	c.Assert(um.Type, Equals, urlTypeIP)
    66  	c.Assert(um.Scheme, Equals, "http")
    67  	c.Assert(um.NetLoc, Equals, "127.0.0.1")
    68  
    69  	um.Init("http://127.0.0.1", false, false)
    70  	c.Assert(um.Type, Equals, urlTypeIP)
    71  	c.Assert(um.Scheme, Equals, "http")
    72  	c.Assert(um.NetLoc, Equals, "127.0.0.1")
    73  	c.Assert(um.getURL("bucket", "object", "params").String(), Equals, "http://127.0.0.1/bucket/object?params")
    74  	c.Assert(um.getURL("", "object", "params").String(), Equals, "http://127.0.0.1/?params")
    75  
    76  	um.Init("https://127.0.0.1:8080", false, false)
    77  	c.Assert(um.Type, Equals, urlTypeIP)
    78  	c.Assert(um.Scheme, Equals, "https")
    79  	c.Assert(um.NetLoc, Equals, "127.0.0.1:8080")
    80  
    81  	um.Init("http://[2401:b180::dc]", false, false)
    82  	c.Assert(um.Type, Equals, urlTypeIP)
    83  	c.Assert(um.Scheme, Equals, "http")
    84  	c.Assert(um.NetLoc, Equals, "[2401:b180::dc]")
    85  
    86  	um.Init("https://[2401:b180::dc]:8080", false, false)
    87  	c.Assert(um.Type, Equals, urlTypeIP)
    88  	c.Assert(um.Scheme, Equals, "https")
    89  	c.Assert(um.NetLoc, Equals, "[2401:b180::dc]:8080")
    90  
    91  	um.InitExt("https://docs.github.com:8080", false, false, true)
    92  	c.Assert(um.Type, Equals, urlTypePathStyle)
    93  	c.Assert(um.Scheme, Equals, "https")
    94  	c.Assert(um.NetLoc, Equals, "docs.github.com:8080")
    95  	c.Assert(um.getURL("bucket", "object", "params").String(), Equals, "https://docs.github.com:8080/bucket/object?params")
    96  	c.Assert(um.getURL("", "object", "params").String(), Equals, "https://docs.github.com:8080/?params")
    97  
    98  	um.InitExt("docs.github.com", false, false, true)
    99  	c.Assert(um.Type, Equals, urlTypePathStyle)
   100  	c.Assert(um.Scheme, Equals, "http")
   101  	c.Assert(um.NetLoc, Equals, "docs.github.com")
   102  
   103  	c.Assert(um.getURL("bucket", "object", "params").String(), Equals, "http://docs.github.com/bucket/object?params")
   104  	c.Assert(um.getURL("bucket", "object", "").String(), Equals, "http://docs.github.com/bucket/object")
   105  	c.Assert(um.getURL("", "object", "").String(), Equals, "http://docs.github.com/")
   106  }
   107  
   108  func (s *OssConnSuite) TestAuth(c *C) {
   109  	endpoint := "https://github.com/"
   110  	cfg := getDefaultOssConfig()
   111  	cfg.AuthVersion = AuthV1
   112  	um := urlMaker{}
   113  	um.Init(endpoint, false, false)
   114  	conn := Conn{cfg, &um, nil}
   115  	uri := um.getURL("bucket", "object", "")
   116  	req := &http.Request{
   117  		Method:     "PUT",
   118  		URL:        uri,
   119  		Proto:      "HTTP/1.1",
   120  		ProtoMajor: 1,
   121  		ProtoMinor: 1,
   122  		Header:     make(http.Header),
   123  		Host:       uri.Host,
   124  	}
   125  
   126  	req.Header.Set("Content-Type", "text/html")
   127  	req.Header.Set("Date", "Thu, 17 Nov 2005 18:49:58 GMT")
   128  	req.Header.Set("Host", endpoint)
   129  	req.Header.Set("X-OSS-Meta-Your", "your")
   130  	req.Header.Set("X-OSS-Meta-Author", "foo@bar.com")
   131  	req.Header.Set("X-OSS-Magic", "abracadabra")
   132  	req.Header.Set("Content-Md5", "ODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=")
   133  
   134  	var akIf Credentials
   135  	credProvider := conn.config.CredentialsProvider
   136  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   137  	conn.signHeader(req, conn.getResource("bucket", "object", ""), akIf)
   138  	testLogger.Println("AUTHORIZATION:", req.Header.Get(HTTPHeaderAuthorization))
   139  }
   140  
   141  func (s *OssConnSuite) TestAuthV1Header(c *C) {
   142  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   143  	cfg := getDefaultOssConfig()
   144  	cfg.AuthVersion = AuthV1
   145  	cfg.AccessKeyID = "ak"
   146  	cfg.AccessKeySecret = "sk"
   147  	um := urlMaker{}
   148  	um.Init(endpoint, false, false)
   149  	conn := Conn{cfg, &um, nil}
   150  	uri := um.getURL("examplebucket", "", "")
   151  	req := &http.Request{
   152  		Method:     "PUT",
   153  		URL:        uri,
   154  		Proto:      "HTTP/1.1",
   155  		ProtoMajor: 1,
   156  		ProtoMinor: 1,
   157  		Header:     make(http.Header),
   158  		Host:       uri.Host,
   159  	}
   160  	req.Header.Add("Content-MD5", "eB5eJF1ptWaXm4bijSPyxw==")
   161  	req.Header.Add("Content-Type", "text/html")
   162  	req.Header.Add("x-oss-meta-author", "alice")
   163  	req.Header.Add("x-oss-meta-magic", "abracadabra")
   164  	req.Header.Add("x-oss-date", "Wed, 28 Dec 2022 10:27:41 GMT")
   165  	req.Header.Add("Date", "Wed, 28 Dec 2022 10:27:41 GMT")
   166  	var akIf Credentials
   167  	credProvider := conn.config.CredentialsProvider
   168  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   169  	conn.signHeader(req, conn.getResource("examplebucket", "nelson", ""), akIf)
   170  	c.Assert("OSS ak:kSHKmLxlyEAKtZPkJhG9bZb5k7M=", Equals, req.Header.Get(HTTPHeaderAuthorization))
   171  
   172  	uri = um.getURL("examplebucket", "", "acl")
   173  	req = &http.Request{
   174  		Method:     "PUT",
   175  		URL:        uri,
   176  		Proto:      "HTTP/1.1",
   177  		ProtoMajor: 1,
   178  		ProtoMinor: 1,
   179  		Header:     make(http.Header),
   180  		Host:       uri.Host,
   181  	}
   182  	req.Header.Add("Content-MD5", "eB5eJF1ptWaXm4bijSPyxw==")
   183  	req.Header.Add("Content-Type", "text/html")
   184  	req.Header.Add("x-oss-meta-author", "alice")
   185  	req.Header.Add("x-oss-meta-magic", "abracadabra")
   186  	req.Header.Add("x-oss-date", "Wed, 28 Dec 2022 10:27:41 GMT")
   187  	req.Header.Add("Date", "Wed, 28 Dec 2022 10:27:41 GMT")
   188  	conn.signHeader(req, conn.getResource("examplebucket", "nelson", "acl"), akIf)
   189  	c.Assert("OSS ak:/afkugFbmWDQ967j1vr6zygBLQk=", Equals, req.Header.Get(HTTPHeaderAuthorization))
   190  
   191  	uri = um.getURL("examplebucket", "", "resourceGroup&non-resousce=null")
   192  	req = &http.Request{
   193  		Method:     "GET",
   194  		URL:        uri,
   195  		Proto:      "HTTP/1.1",
   196  		ProtoMajor: 1,
   197  		ProtoMinor: 1,
   198  		Header:     make(http.Header),
   199  		Host:       uri.Host,
   200  	}
   201  	req.Header.Add("x-oss-date", "Wed, 28 Dec 2022 10:27:41 GMT")
   202  	req.Header.Add("Date", "Wed, 28 Dec 2022 10:27:41 GMT")
   203  	conn.signHeader(req, conn.getResource("examplebucket", "", "resourceGroup"), akIf)
   204  	c.Assert("OSS ak:vkQmfuUDyi1uDi3bKt67oemssIs=", Equals, req.Header.Get(HTTPHeaderAuthorization))
   205  
   206  	uri = um.getURL("examplebucket", "", "resourceGroup&acl")
   207  	req = &http.Request{
   208  		Method:     "GET",
   209  		URL:        uri,
   210  		Proto:      "HTTP/1.1",
   211  		ProtoMajor: 1,
   212  		ProtoMinor: 1,
   213  		Header:     make(http.Header),
   214  		Host:       uri.Host,
   215  	}
   216  	req.Header.Add("x-oss-date", "Wed, 28 Dec 2022 10:27:41 GMT")
   217  	req.Header.Add("Date", "Wed, 28 Dec 2022 10:27:41 GMT")
   218  	params := map[string]interface{}{}
   219  	params["resourceGroup"] = nil
   220  	params["acl"] = nil
   221  	sub := conn.getSubResource(params)
   222  	conn.signHeader(req, conn.getResource("examplebucket", "", sub), akIf)
   223  	c.Assert("OSS ak:x3E5TgOvl/i7PN618s5mEvpJDYk=", Equals, req.Header.Get(HTTPHeaderAuthorization))
   224  }
   225  
   226  func (s *OssConnSuite) TestAuthV1Query(c *C) {
   227  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   228  	cfg := getDefaultOssConfig()
   229  	cfg.AuthVersion = AuthV1
   230  	cfg.AccessKeyID = "ak"
   231  	cfg.AccessKeySecret = "sk"
   232  	um := urlMaker{}
   233  	um.Init(endpoint, false, false)
   234  	conn := Conn{cfg, &um, nil}
   235  	uri := um.getURL("bucket", "key", "versionId=versionId")
   236  	req := &http.Request{
   237  		Method:     "GET",
   238  		URL:        uri,
   239  		Proto:      "HTTP/1.1",
   240  		ProtoMajor: 1,
   241  		ProtoMinor: 1,
   242  		Header:     make(http.Header),
   243  		Host:       uri.Host,
   244  	}
   245  	req.Header.Add("Date", "Sun, 12 Nov 2023 16:43:40 GMT")
   246  	signTime, _ := http.ParseTime("Sun, 12 Nov 2023 16:43:40 GMT")
   247  	params := map[string]interface{}{}
   248  	params["versionId"] = "versionId"
   249  	signUrl, err := conn.signURL("GET", "bucket", "key", signTime.Unix(), params, nil)
   250  	c.Assert(err, IsNil)
   251  	c.Assert("http://bucket.oss-cn-hangzhou.aliyuncs.com/key?Expires=1699807420&OSSAccessKeyId=ak&Signature=dcLTea%2BYh9ApirQ8o8dOPqtvJXQ%3D&versionId=versionId", Equals, signUrl)
   252  
   253  	cfg.SecurityToken = "token"
   254  	uri = um.getURL("bucket", "key+123", "versionId=versionId")
   255  	req = &http.Request{
   256  		Method:     "GET",
   257  		URL:        uri,
   258  		Proto:      "HTTP/1.1",
   259  		ProtoMajor: 1,
   260  		ProtoMinor: 1,
   261  		Header:     make(http.Header),
   262  		Host:       uri.Host,
   263  	}
   264  	req.Header.Add("Date", "Sun, 12 Nov 2023 16:56:44 GMT")
   265  	signTime, _ = http.ParseTime("Sun, 12 Nov 2023 16:56:44 GMT")
   266  	params = map[string]interface{}{}
   267  	params["versionId"] = "versionId"
   268  	signUrl, err = conn.signURL("GET", "bucket", "key+123", signTime.Unix(), params, nil)
   269  	c.Assert(err, IsNil)
   270  	c.Assert("http://bucket.oss-cn-hangzhou.aliyuncs.com/key%2B123?Expires=1699808204&OSSAccessKeyId=ak&Signature=jzKYRrM5y6Br0dRFPaTGOsbrDhY%3D&security-token=token&versionId=versionId", Equals, signUrl)
   271  }
   272  
   273  func (s *OssConnSuite) TestConnToolFunc(c *C) {
   274  	err := CheckRespCode(202, []int{})
   275  	c.Assert(err, NotNil)
   276  
   277  	err = CheckRespCode(202, []int{404})
   278  	c.Assert(err, NotNil)
   279  
   280  	err = CheckRespCode(202, []int{202, 404})
   281  	c.Assert(err, IsNil)
   282  
   283  	srvErr, err := serviceErrFromXML([]byte(""), 312, "")
   284  	c.Assert(err, NotNil)
   285  	c.Assert(srvErr.StatusCode, Equals, 0)
   286  
   287  	srvErr, err = serviceErrFromXML([]byte("ABC"), 312, "")
   288  	c.Assert(err, NotNil)
   289  	c.Assert(srvErr.StatusCode, Equals, 0)
   290  
   291  	srvErr, err = serviceErrFromXML([]byte("<Error></Error>"), 312, "")
   292  	c.Assert(err, IsNil)
   293  	c.Assert(srvErr.StatusCode, Equals, 312)
   294  
   295  	unexpect := UnexpectedStatusCodeError{[]int{200}, 202}
   296  	c.Assert(len(unexpect.Error()) > 0, Equals, true)
   297  	c.Assert(unexpect.Got(), Equals, 202)
   298  
   299  	fd, err := os.Open("../sample/BingWallpaper-2015-11-07.jpg")
   300  	c.Assert(err, IsNil)
   301  	fd.Close()
   302  	var out ProcessObjectResult
   303  	err = jsonUnmarshal(fd, &out)
   304  	c.Assert(err, NotNil)
   305  }
   306  
   307  func (s *OssConnSuite) TestSignRtmpURL(c *C) {
   308  	cfg := getDefaultOssConfig()
   309  
   310  	um := urlMaker{}
   311  	um.Init(endpoint, false, false)
   312  	conn := Conn{cfg, &um, nil}
   313  
   314  	//Anonymous
   315  	channelName := "test-sign-rtmp-url"
   316  	playlistName := "playlist.m3u8"
   317  	expiration := time.Now().Unix() + 3600
   318  	signedRtmpURL := conn.signRtmpURL(bucketName, channelName, playlistName, expiration)
   319  	playURL := getPublishURL(bucketName, channelName)
   320  	hasPrefix := strings.HasPrefix(signedRtmpURL, playURL)
   321  	c.Assert(hasPrefix, Equals, true)
   322  
   323  	//empty playlist name
   324  	playlistName = ""
   325  	signedRtmpURL = conn.signRtmpURL(bucketName, channelName, playlistName, expiration)
   326  	playURL = getPublishURL(bucketName, channelName)
   327  	hasPrefix = strings.HasPrefix(signedRtmpURL, playURL)
   328  	c.Assert(hasPrefix, Equals, true)
   329  }
   330  
   331  func (s *OssConnSuite) TestGetRtmpSignedStr(c *C) {
   332  	cfg := getDefaultOssConfig()
   333  	um := urlMaker{}
   334  	um.Init(endpoint, false, false)
   335  	conn := Conn{cfg, &um, nil}
   336  
   337  	akIf := conn.config.GetCredentials()
   338  
   339  	//Anonymous
   340  	channelName := "test-get-rtmp-signed-str"
   341  	playlistName := "playlist.m3u8"
   342  	expiration := time.Now().Unix() + 3600
   343  	params := map[string]interface{}{}
   344  	signedStr := conn.getRtmpSignedStr(bucketName, channelName, playlistName, expiration, akIf.GetAccessKeySecret(), params)
   345  	c.Assert(signedStr, Equals, "")
   346  }
   347  
   348  func (s *OssConnSuite) TestAuthV4Header(c *C) {
   349  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   350  	cfg := getDefaultOssConfig()
   351  	cfg.AuthVersion = AuthV4
   352  	cfg.AccessKeyID = "ak"
   353  	cfg.AccessKeySecret = "sk"
   354  	cfg.Region = "cn-hangzhou"
   355  	um := urlMaker{}
   356  	um.Init(endpoint, false, false)
   357  	conn := Conn{cfg, &um, nil}
   358  	uri := um.getURL("bucket", "1234+-/123/1.txt", "")
   359  	req := &http.Request{
   360  		Method:     "PUT",
   361  		URL:        uri,
   362  		Proto:      "HTTP/1.1",
   363  		ProtoMajor: 1,
   364  		ProtoMinor: 1,
   365  		Header:     make(http.Header),
   366  		Host:       uri.Host,
   367  	}
   368  	req.Header.Add("x-oss-head1", "value")
   369  	req.Header.Add("abc", "value")
   370  	req.Header.Add("ZAbc", "value")
   371  	req.Header.Add("XYZ", "value")
   372  	req.Header.Add("content-type", "text/plain")
   373  	req.Header.Add("x-oss-content-sha256", "UNSIGNED-PAYLOAD")
   374  	signTime := time.Unix(1702743657, 0).UTC()
   375  	req.Header.Add("x-oss-date", signTime.Format(timeFormatV4))
   376  	req.Header.Add("Date", "Sat, 16 Dec 2023 16:20:57 GMT")
   377  
   378  	params := map[string]interface{}{}
   379  	params["param1"] = "value1"
   380  	params["+param1"] = "value3"
   381  	params["|param1"] = "value4"
   382  	params["+param2"] = nil
   383  	params["|param2"] = nil
   384  	params["param2"] = nil
   385  	sub := conn.getSubResource(params)
   386  	var akIf Credentials
   387  	credProvider := conn.config.CredentialsProvider
   388  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   389  	conn.signHeader(req, conn.getResourceV4("bucket", "1234+-/123/1.txt", sub), akIf)
   390  	c.Assert("OSS4-HMAC-SHA256 Credential=ak/20231216/cn-hangzhou/oss/aliyun_v4_request,Signature=e21d18daa82167720f9b1047ae7e7f1ce7cb77a31e8203a7d5f4624fa0284afe", Equals, req.Header.Get(HTTPHeaderAuthorization))
   391  
   392  }
   393  
   394  func (s *OssConnSuite) TestAuthV4HeaderToken(c *C) {
   395  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   396  	cfg := getDefaultOssConfig()
   397  	cfg.AuthVersion = AuthV4
   398  	cfg.AccessKeyID = "ak"
   399  	cfg.AccessKeySecret = "sk"
   400  	cfg.SecurityToken = "token"
   401  	cfg.Region = "cn-hangzhou"
   402  	um := urlMaker{}
   403  	um.Init(endpoint, false, false)
   404  	conn := Conn{cfg, &um, nil}
   405  	uri := um.getURL("bucket", "1234+-/123/1.txt", "")
   406  	req := &http.Request{
   407  		Method:     "PUT",
   408  		URL:        uri,
   409  		Proto:      "HTTP/1.1",
   410  		ProtoMajor: 1,
   411  		ProtoMinor: 1,
   412  		Header:     make(http.Header),
   413  		Host:       uri.Host,
   414  	}
   415  	req.Header.Add("x-oss-head1", "value")
   416  	req.Header.Add("abc", "value")
   417  	req.Header.Add("ZAbc", "value")
   418  	req.Header.Add("XYZ", "value")
   419  	req.Header.Add("content-type", "text/plain")
   420  	req.Header.Add("x-oss-content-sha256", "UNSIGNED-PAYLOAD")
   421  	signTime := time.Unix(1702784856, 0).UTC()
   422  	req.Header.Add("x-oss-date", signTime.Format(timeFormatV4))
   423  	req.Header.Add("Date", signTime.Format(http.TimeFormat))
   424  	params := map[string]interface{}{}
   425  	params["param1"] = "value1"
   426  	params["+param1"] = "value3"
   427  	params["|param1"] = "value4"
   428  	params["+param2"] = nil
   429  	params["|param2"] = nil
   430  	params["param2"] = nil
   431  	sub := conn.getSubResource(params)
   432  	var akIf Credentials
   433  	credProvider := conn.config.CredentialsProvider
   434  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   435  	if cfg.SecurityToken != "" {
   436  		req.Header.Set(HTTPHeaderOssSecurityToken, akIf.GetSecurityToken())
   437  	}
   438  	conn.signHeader(req, conn.getResourceV4("bucket", "1234+-/123/1.txt", sub), akIf)
   439  	c.Assert("OSS4-HMAC-SHA256 Credential=ak/20231217/cn-hangzhou/oss/aliyun_v4_request,Signature=b94a3f999cf85bcdc00d332fbd3734ba03e48382c36fa4d5af5df817395bd9ea", Equals, req.Header.Get(HTTPHeaderAuthorization))
   440  
   441  }
   442  
   443  func (s *OssConnSuite) TestAuthV4HeaderWithAdditionalHeaders(c *C) {
   444  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   445  	cfg := getDefaultOssConfig()
   446  	cfg.AuthVersion = AuthV4
   447  	cfg.AccessKeyID = "ak"
   448  	cfg.AccessKeySecret = "sk"
   449  	cfg.Region = "cn-hangzhou"
   450  	cfg.AdditionalHeaders = []string{"ZAbc", "abc"}
   451  	um := urlMaker{}
   452  	um.Init(endpoint, false, false)
   453  	conn := Conn{cfg, &um, nil}
   454  	uri := um.getURL("bucket", "1234+-/123/1.txt", "")
   455  	req := &http.Request{
   456  		Method:     "PUT",
   457  		URL:        uri,
   458  		Proto:      "HTTP/1.1",
   459  		ProtoMajor: 1,
   460  		ProtoMinor: 1,
   461  		Header:     make(http.Header),
   462  		Host:       uri.Host,
   463  	}
   464  	req.Header.Add("x-oss-head1", "value")
   465  	req.Header.Add("abc", "value")
   466  	req.Header.Add("ZAbc", "value")
   467  	req.Header.Add("XYZ", "value")
   468  	req.Header.Add("content-type", "text/plain")
   469  	req.Header.Add("x-oss-content-sha256", "UNSIGNED-PAYLOAD")
   470  	signTime := time.Unix(1702747512, 0).UTC()
   471  	req.Header.Add("x-oss-date", signTime.Format(timeFormatV4))
   472  	req.Header.Add("Date", signTime.Format(http.TimeFormat))
   473  	params := map[string]interface{}{}
   474  	params["param1"] = "value1"
   475  	params["+param1"] = "value3"
   476  	params["|param1"] = "value4"
   477  	params["+param2"] = nil
   478  	params["|param2"] = nil
   479  	params["param2"] = nil
   480  	sub := conn.getSubResource(params)
   481  	var akIf Credentials
   482  	credProvider := conn.config.CredentialsProvider
   483  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   484  	if cfg.SecurityToken != "" {
   485  		req.Header.Set(HTTPHeaderOssSecurityToken, akIf.GetSecurityToken())
   486  	}
   487  	conn.signHeader(req, conn.getResourceV4("bucket", "1234+-/123/1.txt", sub), akIf)
   488  	c.Assert("OSS4-HMAC-SHA256 Credential=ak/20231216/cn-hangzhou/oss/aliyun_v4_request,AdditionalHeaders=abc;zabc,Signature=4a4183c187c07c8947db7620deb0a6b38d9fbdd34187b6dbaccb316fa251212f", Equals, req.Header.Get(HTTPHeaderAuthorization))
   489  }
   490  
   491  func (s *OssConnSuite) TestAuthV4Query(c *C) {
   492  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   493  	cfg := getDefaultOssConfig()
   494  	cfg.AuthVersion = AuthV4
   495  	cfg.AccessKeyID = "ak"
   496  	cfg.AccessKeySecret = "sk"
   497  	cfg.Region = "cn-hangzhou"
   498  	um := urlMaker{}
   499  	um.Init(endpoint, false, false)
   500  	conn := Conn{cfg, &um, nil}
   501  	uri := um.getURL("bucket", "1234+-/123/1.txt", "")
   502  	req := &http.Request{
   503  		Method:     "PUT",
   504  		URL:        uri,
   505  		Proto:      "HTTP/1.1",
   506  		ProtoMajor: 1,
   507  		ProtoMinor: 1,
   508  		Header:     make(http.Header),
   509  		Host:       uri.Host,
   510  	}
   511  	req.Header.Add("x-oss-head1", "value")
   512  	req.Header.Add("abc", "value")
   513  	req.Header.Add("ZAbc", "value")
   514  	req.Header.Add("XYZ", "value")
   515  	req.Header.Add("content-type", "application/octet-stream")
   516  	signTime := time.Unix(1702781677, 0).UTC()
   517  	expiresTime := time.Unix(1702782276, 0).UTC()
   518  	params := map[string]interface{}{}
   519  	params["param1"] = "value1"
   520  	params["+param1"] = "value3"
   521  	params["|param1"] = "value4"
   522  	params["+param2"] = nil
   523  	params["|param2"] = nil
   524  	params["param2"] = nil
   525  	var akIf Credentials
   526  	credProvider := conn.config.CredentialsProvider
   527  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   528  	if akIf.GetSecurityToken() != "" {
   529  		params[HTTPParamOssSecurityToken] = akIf.GetSecurityToken()
   530  	}
   531  
   532  	expires := expiresTime.Unix() - signTime.Unix()
   533  	product := conn.config.GetSignProduct()
   534  	region := conn.config.GetSignRegion()
   535  	strDay := signTime.Format(shortTimeFormatV4)
   536  	additionalList, _ := conn.getAdditionalHeaderKeys(req)
   537  
   538  	params[HTTPParamSignatureVersion] = signingAlgorithmV4
   539  	params[HTTPParamCredential] = fmt.Sprintf("%s/%s/%s/%s/aliyun_v4_request", akIf.GetAccessKeyID(), strDay, region, product)
   540  	params[HTTPParamDate] = signTime.Format(timeFormatV4)
   541  	params[HTTPParamExpiresV2] = strconv.FormatInt(expires, 10)
   542  	if len(additionalList) > 0 {
   543  		params[HTTPParamAdditionalHeadersV2] = strings.Join(additionalList, ";")
   544  	}
   545  	bucketName := "bucket"
   546  	objectName := "1234+-/123/1.txt"
   547  	subResource := conn.getSubResource(params)
   548  	canonicalizedResource := conn.getResourceV4(bucketName, objectName, subResource)
   549  	authorizationStr := conn.getSignedStrV4(req, canonicalizedResource, akIf.GetAccessKeySecret(), &signTime)
   550  	params[HTTPParamSignatureV2] = authorizationStr
   551  	urlParams := conn.getURLParams(params)
   552  	signUrl := conn.url.getSignURL(bucketName, objectName, urlParams)
   553  	c.Assert(strings.Contains(signUrl, "x-oss-signature-version=OSS4-HMAC-SHA256"), Equals, true)
   554  	c.Assert(strings.Contains(signUrl, "x-oss-date=20231217T025437Z"), Equals, true)
   555  	c.Assert(strings.Contains(signUrl, "x-oss-expires=599"), Equals, true)
   556  	c.Assert(strings.Contains(signUrl, "x-oss-credential="+url.QueryEscape("ak/20231217/cn-hangzhou/oss/aliyun_v4_request")), Equals, true)
   557  	c.Assert(strings.Contains(signUrl, "x-oss-signature=a39966c61718be0d5b14e668088b3fa07601033f6518ac7b523100014269c0fe"), Equals, true)
   558  	c.Assert("http://bucket.oss-cn-hangzhou.aliyuncs.com/1234%2B-%2F123%2F1.txt?%2Bparam1=value3&%2Bparam2&param1=value1&param2&x-oss-credential=ak%2F20231217%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20231217T025437Z&x-oss-expires=599&x-oss-signature=a39966c61718be0d5b14e668088b3fa07601033f6518ac7b523100014269c0fe&x-oss-signature-version=OSS4-HMAC-SHA256&%7Cparam1=value4&%7Cparam2", Equals, signUrl)
   559  }
   560  
   561  func (s *OssConnSuite) TestAuthV4QueryToken(c *C) {
   562  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   563  	cfg := getDefaultOssConfig()
   564  	cfg.AuthVersion = AuthV4
   565  	cfg.AccessKeyID = "ak"
   566  	cfg.AccessKeySecret = "sk"
   567  	cfg.SecurityToken = "token"
   568  	cfg.Region = "cn-hangzhou"
   569  	um := urlMaker{}
   570  	um.Init(endpoint, false, false)
   571  	conn := Conn{cfg, &um, nil}
   572  	uri := um.getURL("bucket", "1234+-/123/1.txt", "")
   573  	req := &http.Request{
   574  		Method:     "PUT",
   575  		URL:        uri,
   576  		Proto:      "HTTP/1.1",
   577  		ProtoMajor: 1,
   578  		ProtoMinor: 1,
   579  		Header:     make(http.Header),
   580  		Host:       uri.Host,
   581  	}
   582  	req.Header.Add("x-oss-head1", "value")
   583  	req.Header.Add("abc", "value")
   584  	req.Header.Add("ZAbc", "value")
   585  	req.Header.Add("XYZ", "value")
   586  	req.Header.Add("content-type", "application/octet-stream")
   587  	signTime := time.Unix(1702785388, 0).UTC()
   588  	expiresTime := time.Unix(1702785987, 0).UTC()
   589  	params := map[string]interface{}{}
   590  	params["param1"] = "value1"
   591  	params["+param1"] = "value3"
   592  	params["|param1"] = "value4"
   593  	params["+param2"] = nil
   594  	params["|param2"] = nil
   595  	params["param2"] = nil
   596  	var akIf Credentials
   597  	credProvider := conn.config.CredentialsProvider
   598  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   599  	if akIf.GetSecurityToken() != "" {
   600  		params[HTTPParamOssSecurityToken] = akIf.GetSecurityToken()
   601  	}
   602  
   603  	expires := expiresTime.Unix() - signTime.Unix()
   604  	product := conn.config.GetSignProduct()
   605  	region := conn.config.GetSignRegion()
   606  	strDay := signTime.Format(shortTimeFormatV4)
   607  	additionalList, _ := conn.getAdditionalHeaderKeys(req)
   608  
   609  	params[HTTPParamSignatureVersion] = signingAlgorithmV4
   610  	params[HTTPParamCredential] = fmt.Sprintf("%s/%s/%s/%s/aliyun_v4_request", akIf.GetAccessKeyID(), strDay, region, product)
   611  	params[HTTPParamDate] = signTime.Format(timeFormatV4)
   612  	params[HTTPParamExpiresV2] = strconv.FormatInt(expires, 10)
   613  	if len(additionalList) > 0 {
   614  		params[HTTPParamAdditionalHeadersV2] = strings.Join(additionalList, ";")
   615  	}
   616  	bucketName := "bucket"
   617  	objectName := "1234+-/123/1.txt"
   618  	subResource := conn.getSubResource(params)
   619  	canonicalizedResource := conn.getResourceV4(bucketName, objectName, subResource)
   620  	authorizationStr := conn.getSignedStrV4(req, canonicalizedResource, akIf.GetAccessKeySecret(), &signTime)
   621  	params[HTTPParamSignatureV2] = authorizationStr
   622  	urlParams := conn.getURLParams(params)
   623  	signUrl := conn.url.getSignURL(bucketName, objectName, urlParams)
   624  	c.Assert(strings.Contains(signUrl, "x-oss-signature-version=OSS4-HMAC-SHA256"), Equals, true)
   625  	c.Assert(strings.Contains(signUrl, "x-oss-date=20231217T035628Z"), Equals, true)
   626  	c.Assert(strings.Contains(signUrl, "x-oss-expires=599"), Equals, true)
   627  	c.Assert(strings.Contains(signUrl, "x-oss-credential="+url.QueryEscape("ak/20231217/cn-hangzhou/oss/aliyun_v4_request")), Equals, true)
   628  	c.Assert(strings.Contains(signUrl, "x-oss-signature=3817ac9d206cd6dfc90f1c09c00be45005602e55898f26f5ddb06d7892e1f8b5"), Equals, true)
   629  	c.Assert("http://bucket.oss-cn-hangzhou.aliyuncs.com/1234%2B-%2F123%2F1.txt?%2Bparam1=value3&%2Bparam2&param1=value1&param2&x-oss-credential=ak%2F20231217%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20231217T035628Z&x-oss-expires=599&x-oss-security-token=token&x-oss-signature=3817ac9d206cd6dfc90f1c09c00be45005602e55898f26f5ddb06d7892e1f8b5&x-oss-signature-version=OSS4-HMAC-SHA256&%7Cparam1=value4&%7Cparam2", Equals, signUrl)
   630  }
   631  
   632  func (s *OssConnSuite) TestAuthV4QueryWithAdditionalHeaders(c *C) {
   633  	endpoint := "http://oss-cn-hangzhou.aliyuncs.com/"
   634  	cfg := getDefaultOssConfig()
   635  	cfg.AuthVersion = AuthV4
   636  	cfg.AccessKeyID = "ak"
   637  	cfg.AccessKeySecret = "sk"
   638  	cfg.Region = "cn-hangzhou"
   639  	cfg.AdditionalHeaders = []string{"ZAbc", "abc"}
   640  	um := urlMaker{}
   641  	um.Init(endpoint, false, false)
   642  	conn := Conn{cfg, &um, nil}
   643  	uri := um.getURL("bucket", "1234+-/123/1.txt", "")
   644  	req := &http.Request{
   645  		Method:     "PUT",
   646  		URL:        uri,
   647  		Proto:      "HTTP/1.1",
   648  		ProtoMajor: 1,
   649  		ProtoMinor: 1,
   650  		Header:     make(http.Header),
   651  		Host:       uri.Host,
   652  	}
   653  	req.Header.Add("x-oss-head1", "value")
   654  	req.Header.Add("abc", "value")
   655  	req.Header.Add("ZAbc", "value")
   656  	req.Header.Add("XYZ", "value")
   657  	req.Header.Add("content-type", "application/octet-stream")
   658  	signTime := time.Unix(1702783809, 0).UTC()
   659  	expiresTime := time.Unix(1702784408, 0).UTC()
   660  	params := map[string]interface{}{}
   661  	params["param1"] = "value1"
   662  	params["+param1"] = "value3"
   663  	params["|param1"] = "value4"
   664  	params["+param2"] = nil
   665  	params["|param2"] = nil
   666  	params["param2"] = nil
   667  	var akIf Credentials
   668  	credProvider := conn.config.CredentialsProvider
   669  	akIf = credProvider.(CredentialsProvider).GetCredentials()
   670  	if akIf.GetSecurityToken() != "" {
   671  		params[HTTPParamOssSecurityToken] = akIf.GetSecurityToken()
   672  	}
   673  
   674  	expires := expiresTime.Unix() - signTime.Unix()
   675  	product := conn.config.GetSignProduct()
   676  	region := conn.config.GetSignRegion()
   677  	strDay := signTime.Format(shortTimeFormatV4)
   678  	additionalList, _ := conn.getAdditionalHeaderKeys(req)
   679  
   680  	params[HTTPParamSignatureVersion] = signingAlgorithmV4
   681  	params[HTTPParamCredential] = fmt.Sprintf("%s/%s/%s/%s/aliyun_v4_request", akIf.GetAccessKeyID(), strDay, region, product)
   682  	params[HTTPParamDate] = signTime.Format(timeFormatV4)
   683  	params[HTTPParamExpiresV2] = strconv.FormatInt(expires, 10)
   684  	if len(additionalList) > 0 {
   685  		params[HTTPParamAdditionalHeadersV2] = strings.Join(additionalList, ";")
   686  	}
   687  	bucketName := "bucket"
   688  	objectName := "1234+-/123/1.txt"
   689  	subResource := conn.getSubResource(params)
   690  	canonicalizedResource := conn.getResourceV4(bucketName, objectName, subResource)
   691  	authorizationStr := conn.getSignedStrV4(req, canonicalizedResource, akIf.GetAccessKeySecret(), &signTime)
   692  	params[HTTPParamSignatureV2] = authorizationStr
   693  	urlParams := conn.getURLParams(params)
   694  	signUrl := conn.url.getSignURL(bucketName, objectName, urlParams)
   695  	c.Assert(strings.Contains(signUrl, "x-oss-signature-version=OSS4-HMAC-SHA256"), Equals, true)
   696  	c.Assert(strings.Contains(signUrl, "x-oss-date=20231217T033009Z"), Equals, true)
   697  	c.Assert(strings.Contains(signUrl, "x-oss-expires=599"), Equals, true)
   698  	c.Assert(strings.Contains(signUrl, "x-oss-credential="+url.QueryEscape("ak/20231217/cn-hangzhou/oss/aliyun_v4_request")), Equals, true)
   699  	c.Assert(strings.Contains(signUrl, "x-oss-signature=6bd984bfe531afb6db1f7550983a741b103a8c58e5e14f83ea474c2322dfa2b7"), Equals, true)
   700  	c.Assert(strings.Contains(signUrl, "x-oss-additional-headers="+url.QueryEscape("abc;zabc")), Equals, true)
   701  	c.Assert("http://bucket.oss-cn-hangzhou.aliyuncs.com/1234%2B-%2F123%2F1.txt?%2Bparam1=value3&%2Bparam2&param1=value1&param2&x-oss-additional-headers=abc%3Bzabc&x-oss-credential=ak%2F20231217%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20231217T033009Z&x-oss-expires=599&x-oss-signature=6bd984bfe531afb6db1f7550983a741b103a8c58e5e14f83ea474c2322dfa2b7&x-oss-signature-version=OSS4-HMAC-SHA256&%7Cparam1=value4&%7Cparam2", Equals, signUrl)
   702  }