1package cos 2 3import ( 4 "context" 5 "fmt" 6 "net/http" 7 "net/url" 8 "reflect" 9 "testing" 10 "time" 11) 12 13func TestNewAuthorization(t *testing.T) { 14 expectAuthorization := `q-sign-algorithm=sha1&q-ak=QmFzZTY0IGlzIGEgZ2VuZXJp&q-sign-time=1480932292;1481012292&q-key-time=1480932292;1481012292&q-header-list=host;x-cos-content-sha1;x-cos-stroage-class&q-url-param-list=&q-signature=91f7814df035319aa08d47e5a7a66ea989d57301` 15 secretID := "QmFzZTY0IGlzIGEgZ2VuZXJp" 16 secretKey := "AKIDZfbOA78asKUYBcXFrJD0a1ICvR98JM" 17 host := "testbucket-125000000.cos.ap-beijing-1.myqcloud.com" 18 uri := "https://testbucket-125000000.cos.ap-beijing-1.myqcloud.com/testfile2" 19 startTime := time.Unix(int64(1480932292), 0) 20 endTime := time.Unix(int64(1481012292), 0) 21 22 req, _ := http.NewRequest("PUT", uri, nil) 23 req.Header.Add("Host", host) 24 req.Header.Add("x-cos-content-sha1", "db8ac1c259eb89d4a131b253bacfca5f319d54f2") 25 req.Header.Add("x-cos-stroage-class", "nearline") 26 27 authTime := &AuthTime{ 28 SignStartTime: startTime, 29 SignEndTime: endTime, 30 KeyStartTime: startTime, 31 KeyEndTime: endTime, 32 } 33 auth := newAuthorization(Auth{ 34 SecretID: secretID, 35 SecretKey: secretKey, 36 }, req, *authTime) 37 38 if auth != expectAuthorization { 39 t.Errorf("NewAuthorization returned \n%#v, want \n%#v", auth, expectAuthorization) 40 } 41} 42 43func TestAuthorizationTransport(t *testing.T) { 44 setup() 45 defer teardown() 46 47 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 48 auth := r.Header.Get("Authorization") 49 if auth == "" { 50 t.Error("AuthorizationTransport didn't add Authorization header") 51 } 52 }) 53 54 (client.Sender).(*DefaultSender).Transport = &AuthorizationTransport{} 55 req, _ := http.NewRequest("GET", client.BaseURL.BucketURL.String(), nil) 56 req.Header.Set("X-Testing", "0") 57 client.doAPI(context.Background(), Caller{}, req, nil, true) 58} 59 60func TestAuthorizationTransportWithSessionToken(t *testing.T) { 61 setup() 62 defer teardown() 63 64 sessionToken := "CxQQbwSzzX5obZm23yEcyQtpROuDB0Q60d322a47737c8241991d12dc4b8387c7J6NL50eH1BYN6VnFYB_Ml6oPZzUxz5wxDGVvvgxZXr1m-4HvmkvmMH4YB02XdVPapKp7oGnrMous2jsSTALo4iU2fuRclbVw-czYwggSxuNxXAwmqcT1HpD3h3zc3e24sryIhJKqzSOczQZjtGrxSSQ4K23o9Mx8VHgrosliU0aIiI2KFhxJhij03SzDDOQcBAwpFZyM0NvpOdN6b14yJbrt9bAzYGNjX-PeU3MXfi0" 65 66 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 67 auth := r.Header.Get("Authorization") 68 if auth == "" { 69 t.Error("AuthorizationTransport didn't add Authorization header") 70 } 71 token := r.Header.Get("x-cos-security-token") 72 if token == "" { 73 t.Error("AuthorizationTransport didn't add x-cos-security-token header") 74 } 75 if token != sessionToken { 76 t.Errorf("AuthorizationTransport didn't add expected x-cos-security-token header, expected: %s, got: %s", sessionToken, token) 77 } 78 }) 79 80 (client.Sender).(*DefaultSender).Transport = &AuthorizationTransport{ 81 SecretID: "233", 82 SecretKey: "666", 83 SessionToken: sessionToken, 84 } 85 req, _ := http.NewRequest("GET", client.BaseURL.BucketURL.String(), nil) 86 req.Header.Set("X-Testing", "0") 87 client.doAPI(context.Background(), Caller{}, req, nil, true) 88} 89 90func TestAuthorizationTransport_skip_PresignedURL(t *testing.T) { 91 setup() 92 defer teardown() 93 94 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 95 _, exist := r.Header["Authorization"] 96 if exist { 97 t.Error("AuthorizationTransport add Authorization header when use PresignedURL") 98 } 99 }) 100 101 (client.Sender).(*DefaultSender).Transport = &AuthorizationTransport{} 102 sign := "q-sign-algorithm=sha1&q-ak=QmFzZTY0IGlzIGEgZ2VuZXJp&q-sign-time=1480932292;1481012292&q-key-time=1480932292;1481012292&q-header-list=&q-url-param-list=&q-signature=a5de76b0734f084a7ea24413f7168b4bdbe5676c" 103 u := fmt.Sprintf("%s?sign=%s", client.BaseURL.BucketURL.String(), sign) 104 req, _ := http.NewRequest("GET", u, nil) 105 client.doAPI(context.Background(), Caller{}, req, nil, true) 106} 107 108func TestAuthorizationTransport_with_another_transport(t *testing.T) { 109 setup() 110 defer teardown() 111 112 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 113 auth := r.Header.Get("Authorization") 114 if auth == "" { 115 t.Error("AuthorizationTransport didn't add Authorization header") 116 } 117 }) 118 119 tr := &testingTransport{} 120 (client.Sender).(*DefaultSender).Transport = &AuthorizationTransport{ 121 Transport: tr, 122 } 123 req, _ := http.NewRequest("GET", client.BaseURL.BucketURL.String(), nil) 124 req.Header.Set("X-Testing", "0") 125 client.doAPI(context.Background(), Caller{}, req, nil, true) 126 if tr.called != 1 { 127 t.Error("AuthorizationTransport not call another Transport") 128 } 129} 130 131type testingTransport struct { 132 called int 133} 134 135func (t *testingTransport) RoundTrip(req *http.Request) (*http.Response, error) { 136 t.called++ 137 return http.DefaultTransport.RoundTrip(req) 138} 139 140func Test_camSafeURLEncode(t *testing.T) { 141 type args struct { 142 s string 143 } 144 tests := []struct { 145 name string 146 args args 147 want string 148 }{ 149 { 150 name: "no replace", 151 args: args{"1234 +abc0AB#@"}, 152 want: "1234%20%2Babc0AB%23%40", 153 }, 154 { 155 name: "replace", 156 args: args{"1234 +abc0AB#@,!'()*"}, 157 want: "1234%20%2Babc0AB%23%40%2C%21%27%28%29%2A", 158 }, 159 } 160 for _, tt := range tests { 161 t.Run(tt.name, func(t *testing.T) { 162 if got := camSafeURLEncode(tt.args.s); got != tt.want { 163 t.Errorf("camSafeURLEncode() = %v, want %v", got, tt.want) 164 } 165 }) 166 } 167} 168 169func Test_valuesForSign_Encode(t *testing.T) { 170 tests := []struct { 171 name string 172 vs valuesForSign 173 want string 174 }{ 175 { 176 name: "test escape", 177 vs: valuesForSign{ 178 "test+233": {"value 666"}, 179 "test+234": {"value 667"}, 180 }, 181 want: "test%2B233=value%20666&test%2B234=value%20667", 182 }, 183 { 184 name: "test order", 185 vs: valuesForSign{ 186 "test_233": {"value_666"}, 187 "233": {"value_2"}, 188 "test_666": {"value_123"}, 189 }, 190 want: "233=value_2&test_233=value_666&test_666=value_123", 191 }, 192 } 193 for _, tt := range tests { 194 t.Run(tt.name, func(t *testing.T) { 195 if got := tt.vs.Encode(); got != tt.want { 196 t.Errorf("valuesForSign.Encode() = %v, want %v", got, tt.want) 197 } 198 }) 199 } 200} 201 202func Test_valuesForSign_Add(t *testing.T) { 203 type args struct { 204 key string 205 value string 206 } 207 tests := []struct { 208 name string 209 vs valuesForSign 210 args args 211 want valuesForSign 212 }{ 213 { 214 name: "add new key", 215 vs: valuesForSign{}, 216 args: args{"test_key", "value_233"}, 217 want: valuesForSign{"test_key": {"value_233"}}, 218 }, 219 { 220 name: "extend key", 221 vs: valuesForSign{"test_key": {"value_233"}}, 222 args: args{"test_key", "value_666"}, 223 want: valuesForSign{"test_key": {"value_233", "value_666"}}, 224 }, 225 { 226 name: "key to lower(add)", 227 vs: valuesForSign{}, 228 args: args{"TEST_KEY", "value_233"}, 229 want: valuesForSign{"test_key": {"value_233"}}, 230 }, 231 { 232 name: "key to lower(extend)", 233 vs: valuesForSign{"test_key": {"value_233"}}, 234 args: args{"TEST_KEY", "value_666"}, 235 want: valuesForSign{"test_key": {"value_233", "value_666"}}, 236 }, 237 } 238 for _, tt := range tests { 239 t.Run(tt.name, func(t *testing.T) { 240 tt.vs.Add(tt.args.key, tt.args.value) 241 if !reflect.DeepEqual(tt.vs, tt.want) { 242 t.Errorf("%v, want %v", tt.vs, tt.want) 243 } 244 }) 245 } 246} 247 248func Test_genFormatParameters(t *testing.T) { 249 type args struct { 250 parameters url.Values 251 } 252 tests := []struct { 253 name string 254 args args 255 wantFormatParameters string 256 wantSignedParameterList []string 257 }{ 258 { 259 name: "test order", 260 args: args{url.Values{ 261 "test_key_233": {"666"}, 262 "233": {"222"}, 263 "test_key_2": {"value"}, 264 }}, 265 wantFormatParameters: "233=222&test_key_2=value&test_key_233=666", 266 wantSignedParameterList: []string{"233", "test_key_2", "test_key_233"}, 267 }, 268 { 269 name: "test escape", 270 args: args{url.Values{ 271 "Test+key": {"666 value"}, 272 "233 666": {"22+2"}, 273 }}, 274 wantFormatParameters: "233%20666=22%2B2&test%2Bkey=666%20value", 275 wantSignedParameterList: []string{"233 666", "test+key"}, 276 }, 277 } 278 for _, tt := range tests { 279 t.Run(tt.name, func(t *testing.T) { 280 gotFormatParameters, gotSignedParameterList := genFormatParameters(tt.args.parameters) 281 if gotFormatParameters != tt.wantFormatParameters { 282 t.Errorf("genFormatParameters() gotFormatParameters = %v, want %v", gotFormatParameters, tt.wantFormatParameters) 283 } 284 if !reflect.DeepEqual(gotSignedParameterList, tt.wantSignedParameterList) { 285 t.Errorf("genFormatParameters() gotSignedParameterList = %v, want %v", gotSignedParameterList, tt.wantSignedParameterList) 286 } 287 }) 288 } 289} 290 291func Test_genFormatHeaders(t *testing.T) { 292 type args struct { 293 headers http.Header 294 } 295 tests := []struct { 296 name string 297 args args 298 wantFormatHeaders string 299 wantSignedHeaderList []string 300 }{ 301 { 302 name: "test order", 303 args: args{http.Header{ 304 "host": {"example.com"}, 305 "content-length": {"22"}, 306 "content-md5": {"xxx222"}, 307 }}, 308 wantFormatHeaders: "content-length=22&content-md5=xxx222&host=example.com", 309 wantSignedHeaderList: []string{"content-length", "content-md5", "host"}, 310 }, 311 { 312 name: "test escape", 313 args: args{http.Header{ 314 "host": {"example.com"}, 315 "content-length": {"22"}, 316 "Content-Disposition": {"attachment; filename=hello - world!(+).go"}, 317 }}, 318 wantFormatHeaders: "content-disposition=attachment%3B%20filename%3Dhello%20-%20world%21%28%2B%29.go&content-length=22&host=example.com", 319 wantSignedHeaderList: []string{"content-disposition", "content-length", "host"}, 320 }, 321 { 322 name: "test skip key", 323 args: args{http.Header{ 324 "Host": {"example.com"}, 325 "content-length": {"22"}, 326 "x-cos-xyz": {"lala"}, 327 "Content-Type": {"text/html"}, 328 }}, 329 wantFormatHeaders: "content-length=22&host=example.com&x-cos-xyz=lala", 330 wantSignedHeaderList: []string{"content-length", "host", "x-cos-xyz"}, 331 }, 332 } 333 for _, tt := range tests { 334 t.Run(tt.name, func(t *testing.T) { 335 gotFormatHeaders, gotSignedHeaderList := genFormatHeaders(tt.args.headers) 336 if gotFormatHeaders != tt.wantFormatHeaders { 337 t.Errorf("genFormatHeaders() gotFormatHeaders = %v, want %v", gotFormatHeaders, tt.wantFormatHeaders) 338 } 339 if !reflect.DeepEqual(gotSignedHeaderList, tt.wantSignedHeaderList) { 340 t.Errorf("genFormatHeaders() gotSignedHeaderList = %v, want %v", gotSignedHeaderList, tt.wantSignedHeaderList) 341 } 342 }) 343 } 344} 345