yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/huawei/obs/trait.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Copyright 2019 Huawei Technologies Co.,Ltd. 16 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use 17 // this file except in compliance with the License. You may obtain a copy of the 18 // License at 19 // 20 // http://www.apache.org/licenses/LICENSE-2.0 21 // 22 // Unless required by applicable law or agreed to in writing, software distributed 23 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 24 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 25 // specific language governing permissions and limitations under the License. 26 27 package obs 28 29 import ( 30 "bytes" 31 "fmt" 32 "io" 33 "os" 34 "strings" 35 ) 36 37 type IReadCloser interface { 38 setReadCloser(body io.ReadCloser) 39 } 40 41 func (output *GetObjectOutput) setReadCloser(body io.ReadCloser) { 42 output.Body = body 43 } 44 45 func setHeaders(headers map[string][]string, header string, headerValue []string, isObs bool) { 46 if isObs { 47 header = HEADER_PREFIX_OBS + header 48 headers[header] = headerValue 49 } else { 50 header = HEADER_PREFIX + header 51 headers[header] = headerValue 52 } 53 } 54 55 func setHeadersNext(headers map[string][]string, header string, headerNext string, headerValue []string, isObs bool) { 56 if isObs { 57 headers[header] = headerValue 58 } else { 59 headers[headerNext] = headerValue 60 } 61 } 62 63 type IBaseModel interface { 64 setStatusCode(statusCode int) 65 66 setRequestId(requestId string) 67 68 setResponseHeaders(responseHeaders map[string][]string) 69 } 70 71 type ISerializable interface { 72 trans(isObs bool) (map[string]string, map[string][]string, interface{}, error) 73 } 74 75 type DefaultSerializable struct { 76 params map[string]string 77 headers map[string][]string 78 data interface{} 79 } 80 81 func (input DefaultSerializable) trans(isObs bool) (map[string]string, map[string][]string, interface{}, error) { 82 return input.params, input.headers, input.data, nil 83 } 84 85 var defaultSerializable = &DefaultSerializable{} 86 87 func newSubResourceSerial(subResource SubResourceType) *DefaultSerializable { 88 return &DefaultSerializable{map[string]string{string(subResource): ""}, nil, nil} 89 } 90 91 func trans(subResource SubResourceType, input interface{}) (params map[string]string, headers map[string][]string, data interface{}, err error) { 92 params = map[string]string{string(subResource): ""} 93 data, err = ConvertRequestToIoReader(input) 94 return 95 } 96 97 func (baseModel *BaseModel) setStatusCode(statusCode int) { 98 baseModel.StatusCode = statusCode 99 } 100 101 func (baseModel *BaseModel) setRequestId(requestId string) { 102 baseModel.RequestId = requestId 103 } 104 105 func (baseModel *BaseModel) setResponseHeaders(responseHeaders map[string][]string) { 106 baseModel.ResponseHeaders = responseHeaders 107 } 108 109 func (input ListBucketsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 110 headers = make(map[string][]string) 111 if input.QueryLocation && !isObs { 112 setHeaders(headers, HEADER_LOCATION_AMZ, []string{"true"}, isObs) 113 } 114 return 115 } 116 117 func (input CreateBucketInput) prepareGrantHeaders(headers map[string][]string, isObs bool) { 118 if grantReadId := input.GrantReadId; grantReadId != "" { 119 setHeaders(headers, HEADER_GRANT_READ_OBS, []string{grantReadId}, isObs) 120 } 121 if grantWriteId := input.GrantWriteId; grantWriteId != "" { 122 setHeaders(headers, HEADER_GRANT_WRITE_OBS, []string{grantWriteId}, isObs) 123 } 124 if grantReadAcpId := input.GrantReadAcpId; grantReadAcpId != "" { 125 setHeaders(headers, HEADER_GRANT_READ_ACP_OBS, []string{grantReadAcpId}, isObs) 126 } 127 if grantWriteAcpId := input.GrantWriteAcpId; grantWriteAcpId != "" { 128 setHeaders(headers, HEADER_GRANT_WRITE_ACP_OBS, []string{grantWriteAcpId}, isObs) 129 } 130 if grantFullControlId := input.GrantFullControlId; grantFullControlId != "" { 131 setHeaders(headers, HEADER_GRANT_FULL_CONTROL_OBS, []string{grantFullControlId}, isObs) 132 } 133 if grantReadDeliveredId := input.GrantReadDeliveredId; grantReadDeliveredId != "" { 134 setHeaders(headers, HEADER_GRANT_READ_DELIVERED_OBS, []string{grantReadDeliveredId}, true) 135 } 136 if grantFullControlDeliveredId := input.GrantFullControlDeliveredId; grantFullControlDeliveredId != "" { 137 setHeaders(headers, HEADER_GRANT_FULL_CONTROL_DELIVERED_OBS, []string{grantFullControlDeliveredId}, true) 138 } 139 } 140 141 func (input CreateBucketInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 142 headers = make(map[string][]string) 143 if acl := string(input.ACL); acl != "" { 144 setHeaders(headers, HEADER_ACL, []string{acl}, isObs) 145 } 146 if storageClass := string(input.StorageClass); storageClass != "" { 147 if !isObs { 148 if storageClass == string(StorageClassWarm) { 149 storageClass = string(storageClassStandardIA) 150 } else if storageClass == string(StorageClassCold) { 151 storageClass = string(storageClassGlacier) 152 } 153 } 154 setHeadersNext(headers, HEADER_STORAGE_CLASS_OBS, HEADER_STORAGE_CLASS, []string{storageClass}, isObs) 155 if epid := input.Epid; epid != "" { 156 setHeaders(headers, HEADER_EPID_HEADERS, []string{epid}, isObs) 157 } 158 } 159 input.prepareGrantHeaders(headers, isObs) 160 if location := strings.TrimSpace(input.Location); location != "" { 161 input.Location = location 162 163 xml := make([]string, 0, 3) 164 xml = append(xml, "<CreateBucketConfiguration>") 165 if isObs { 166 xml = append(xml, fmt.Sprintf("<Location>%s</Location>", input.Location)) 167 } else { 168 xml = append(xml, fmt.Sprintf("<LocationConstraint>%s</LocationConstraint>", input.Location)) 169 } 170 xml = append(xml, "</CreateBucketConfiguration>") 171 172 data = strings.Join(xml, "") 173 } 174 return 175 } 176 177 func (input SetBucketStoragePolicyInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 178 xml := make([]string, 0, 1) 179 if !isObs { 180 storageClass := "STANDARD" 181 if input.StorageClass == StorageClassWarm { 182 storageClass = string(storageClassStandardIA) 183 } else if input.StorageClass == StorageClassCold { 184 storageClass = string(storageClassGlacier) 185 } 186 params = map[string]string{string(SubResourceStoragePolicy): ""} 187 xml = append(xml, fmt.Sprintf("<StoragePolicy><DefaultStorageClass>%s</DefaultStorageClass></StoragePolicy>", storageClass)) 188 } else { 189 if input.StorageClass != StorageClassWarm && input.StorageClass != StorageClassCold { 190 input.StorageClass = StorageClassStandard 191 } 192 params = map[string]string{string(SubResourceStorageClass): ""} 193 xml = append(xml, fmt.Sprintf("<StorageClass>%s</StorageClass>", input.StorageClass)) 194 } 195 data = strings.Join(xml, "") 196 return 197 } 198 199 func (input ListObjsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 200 params = make(map[string]string) 201 if input.Prefix != "" { 202 params["prefix"] = input.Prefix 203 } 204 if input.Delimiter != "" { 205 params["delimiter"] = input.Delimiter 206 } 207 if input.MaxKeys > 0 { 208 params["max-keys"] = IntToString(input.MaxKeys) 209 } 210 headers = make(map[string][]string) 211 if origin := strings.TrimSpace(input.Origin); origin != "" { 212 headers[HEADER_ORIGIN_CAMEL] = []string{origin} 213 } 214 if requestHeader := strings.TrimSpace(input.RequestHeader); requestHeader != "" { 215 headers[HEADER_ACCESS_CONTROL_REQUEST_HEADER_CAMEL] = []string{requestHeader} 216 } 217 return 218 } 219 220 func (input ListObjectsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 221 params, headers, data, err = input.ListObjsInput.trans(isObs) 222 if err != nil { 223 return 224 } 225 if input.Marker != "" { 226 params["marker"] = input.Marker 227 } 228 return 229 } 230 231 func (input ListVersionsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 232 params, headers, data, err = input.ListObjsInput.trans(isObs) 233 if err != nil { 234 return 235 } 236 params[string(SubResourceVersions)] = "" 237 if input.KeyMarker != "" { 238 params["key-marker"] = input.KeyMarker 239 } 240 if input.VersionIdMarker != "" { 241 params["version-id-marker"] = input.VersionIdMarker 242 } 243 return 244 } 245 246 func (input ListMultipartUploadsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 247 params = map[string]string{string(SubResourceUploads): ""} 248 if input.Prefix != "" { 249 params["prefix"] = input.Prefix 250 } 251 if input.Delimiter != "" { 252 params["delimiter"] = input.Delimiter 253 } 254 if input.MaxUploads > 0 { 255 params["max-uploads"] = IntToString(input.MaxUploads) 256 } 257 if input.KeyMarker != "" { 258 params["key-marker"] = input.KeyMarker 259 } 260 if input.UploadIdMarker != "" { 261 params["upload-id-marker"] = input.UploadIdMarker 262 } 263 return 264 } 265 266 func (input SetBucketQuotaInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 267 return trans(SubResourceQuota, input) 268 } 269 270 func (input SetBucketAclInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 271 params = map[string]string{string(SubResourceAcl): ""} 272 headers = make(map[string][]string) 273 274 if acl := string(input.ACL); acl != "" { 275 setHeaders(headers, HEADER_ACL, []string{acl}, isObs) 276 } else { 277 data, _ = convertBucketAclToXml(input.AccessControlPolicy, false, isObs) 278 } 279 return 280 } 281 282 func (input SetBucketPolicyInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 283 params = map[string]string{string(SubResourcePolicy): ""} 284 data = strings.NewReader(input.Policy) 285 return 286 } 287 288 func (input SetBucketCorsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 289 params = map[string]string{string(SubResourceCors): ""} 290 data, md5, err := ConvertRequestToIoReaderV2(input) 291 if err != nil { 292 return 293 } 294 headers = map[string][]string{HEADER_MD5_CAMEL: []string{md5}} 295 return 296 } 297 298 func (input SetBucketVersioningInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 299 return trans(SubResourceVersioning, input) 300 } 301 302 func (input SetBucketWebsiteConfigurationInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 303 params = map[string]string{string(SubResourceWebsite): ""} 304 data, _ = ConvertWebsiteConfigurationToXml(input.BucketWebsiteConfiguration, false) 305 return 306 } 307 308 func (input GetBucketMetadataInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 309 headers = make(map[string][]string) 310 if origin := strings.TrimSpace(input.Origin); origin != "" { 311 headers[HEADER_ORIGIN_CAMEL] = []string{origin} 312 } 313 if requestHeader := strings.TrimSpace(input.RequestHeader); requestHeader != "" { 314 headers[HEADER_ACCESS_CONTROL_REQUEST_HEADER_CAMEL] = []string{requestHeader} 315 } 316 return 317 } 318 319 func (input SetBucketLoggingConfigurationInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 320 params = map[string]string{string(SubResourceLogging): ""} 321 data, _ = ConvertLoggingStatusToXml(input.BucketLoggingStatus, false, isObs) 322 return 323 } 324 325 func (input SetBucketLifecycleConfigurationInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 326 params = map[string]string{string(SubResourceLifecycle): ""} 327 data, md5 := ConvertLifecyleConfigurationToXml(input.BucketLifecyleConfiguration, true, isObs) 328 headers = map[string][]string{HEADER_MD5_CAMEL: []string{md5}} 329 return 330 } 331 332 func (input SetBucketTaggingInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 333 params = map[string]string{string(SubResourceTagging): ""} 334 data, md5, err := ConvertRequestToIoReaderV2(input) 335 if err != nil { 336 return 337 } 338 headers = map[string][]string{HEADER_MD5_CAMEL: []string{md5}} 339 return 340 } 341 342 func (input SetBucketNotificationInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 343 params = map[string]string{string(SubResourceNotification): ""} 344 data, _ = ConvertNotificationToXml(input.BucketNotification, false, isObs) 345 return 346 } 347 348 func (input DeleteObjectInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 349 params = make(map[string]string) 350 if input.VersionId != "" { 351 params[PARAM_VERSION_ID] = input.VersionId 352 } 353 return 354 } 355 356 func (input DeleteObjectsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 357 params = map[string]string{string(SubResourceDelete): ""} 358 data, md5, err := ConvertRequestToIoReaderV2(input) 359 if err != nil { 360 return 361 } 362 headers = map[string][]string{HEADER_MD5_CAMEL: []string{md5}} 363 return 364 } 365 366 func (input SetObjectAclInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 367 params = map[string]string{string(SubResourceAcl): ""} 368 if input.VersionId != "" { 369 params[PARAM_VERSION_ID] = input.VersionId 370 } 371 headers = make(map[string][]string) 372 if acl := string(input.ACL); acl != "" { 373 setHeaders(headers, HEADER_ACL, []string{acl}, isObs) 374 } else { 375 data, _ = ConvertAclToXml(input.AccessControlPolicy, false, isObs) 376 } 377 return 378 } 379 380 func (input GetObjectAclInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 381 params = map[string]string{string(SubResourceAcl): ""} 382 if input.VersionId != "" { 383 params[PARAM_VERSION_ID] = input.VersionId 384 } 385 return 386 } 387 388 func (input RestoreObjectInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 389 params = map[string]string{string(SubResourceRestore): ""} 390 if input.VersionId != "" { 391 params[PARAM_VERSION_ID] = input.VersionId 392 } 393 if !isObs { 394 data, err = ConvertRequestToIoReader(input) 395 } else { 396 data = ConverntObsRestoreToXml(input) 397 } 398 return 399 } 400 401 func (header SseKmsHeader) GetEncryption() string { 402 if header.Encryption != "" { 403 return header.Encryption 404 } 405 if !header.isObs { 406 return DEFAULT_SSE_KMS_ENCRYPTION 407 } 408 return DEFAULT_SSE_KMS_ENCRYPTION_OBS 409 } 410 411 func (header SseKmsHeader) GetKey() string { 412 return header.Key 413 } 414 415 func (header SseCHeader) GetEncryption() string { 416 if header.Encryption != "" { 417 return header.Encryption 418 } 419 return DEFAULT_SSE_C_ENCRYPTION 420 } 421 422 func (header SseCHeader) GetKey() string { 423 return header.Key 424 } 425 426 func (header SseCHeader) GetKeyMD5() string { 427 if header.KeyMD5 != "" { 428 return header.KeyMD5 429 } 430 431 if ret, err := Base64Decode(header.GetKey()); err == nil { 432 return Base64Md5(ret) 433 } 434 return "" 435 } 436 437 func setSseHeader(headers map[string][]string, sseHeader ISseHeader, sseCOnly bool, isObs bool) { 438 if sseHeader != nil { 439 if sseCHeader, ok := sseHeader.(SseCHeader); ok { 440 setHeaders(headers, HEADER_SSEC_ENCRYPTION, []string{sseCHeader.GetEncryption()}, isObs) 441 setHeaders(headers, HEADER_SSEC_KEY, []string{sseCHeader.GetKey()}, isObs) 442 setHeaders(headers, HEADER_SSEC_KEY_MD5, []string{sseCHeader.GetEncryption()}, isObs) 443 } else if sseKmsHeader, ok := sseHeader.(SseKmsHeader); !sseCOnly && ok { 444 sseKmsHeader.isObs = isObs 445 setHeaders(headers, HEADER_SSEKMS_ENCRYPTION, []string{sseKmsHeader.GetEncryption()}, isObs) 446 setHeadersNext(headers, HEADER_SSEKMS_KEY_OBS, HEADER_SSEKMS_KEY_AMZ, []string{sseKmsHeader.GetKey()}, isObs) 447 } 448 } 449 } 450 451 func (input GetObjectMetadataInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 452 params = make(map[string]string) 453 if input.VersionId != "" { 454 params[PARAM_VERSION_ID] = input.VersionId 455 } 456 headers = make(map[string][]string) 457 458 if input.Origin != "" { 459 headers[HEADER_ORIGIN_CAMEL] = []string{input.Origin} 460 } 461 462 if input.RequestHeader != "" { 463 headers[HEADER_ACCESS_CONTROL_REQUEST_HEADER_CAMEL] = []string{input.RequestHeader} 464 } 465 setSseHeader(headers, input.SseHeader, true, isObs) 466 return 467 } 468 469 func (input SetObjectMetadataInput) prepareContentHeaders(headers map[string][]string) { 470 if input.ContentDisposition != "" { 471 headers[HEADER_CONTENT_DISPOSITION_CAMEL] = []string{input.ContentDisposition} 472 } 473 if input.ContentEncoding != "" { 474 headers[HEADER_CONTENT_ENCODING_CAMEL] = []string{input.ContentEncoding} 475 } 476 if input.ContentLanguage != "" { 477 headers[HEADER_CONTENT_LANGUAGE_CAMEL] = []string{input.ContentLanguage} 478 } 479 480 if input.ContentType != "" { 481 headers[HEADER_CONTENT_TYPE_CAML] = []string{input.ContentType} 482 } 483 } 484 485 func (input SetObjectMetadataInput) prepareStorageClass(headers map[string][]string, isObs bool) { 486 if storageClass := string(input.StorageClass); storageClass != "" { 487 if !isObs { 488 if storageClass == string(StorageClassWarm) { 489 storageClass = string(storageClassStandardIA) 490 } else if storageClass == string(StorageClassCold) { 491 storageClass = string(storageClassGlacier) 492 } 493 } 494 setHeaders(headers, HEADER_STORAGE_CLASS2, []string{storageClass}, isObs) 495 } 496 } 497 498 func (input SetObjectMetadataInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 499 params = make(map[string]string) 500 params = map[string]string{string(SubResourceMetadata): ""} 501 if input.VersionId != "" { 502 params[PARAM_VERSION_ID] = input.VersionId 503 } 504 headers = make(map[string][]string) 505 506 if directive := string(input.MetadataDirective); directive != "" { 507 setHeaders(headers, HEADER_METADATA_DIRECTIVE, []string{string(input.MetadataDirective)}, isObs) 508 } else { 509 setHeaders(headers, HEADER_METADATA_DIRECTIVE, []string{string(ReplaceNew)}, isObs) 510 } 511 if input.CacheControl != "" { 512 headers[HEADER_CACHE_CONTROL_CAMEL] = []string{input.CacheControl} 513 } 514 input.prepareContentHeaders(headers) 515 if input.Expires != "" { 516 headers[HEADER_EXPIRES_CAMEL] = []string{input.Expires} 517 } 518 if input.WebsiteRedirectLocation != "" { 519 setHeaders(headers, HEADER_WEBSITE_REDIRECT_LOCATION, []string{input.WebsiteRedirectLocation}, isObs) 520 } 521 input.prepareStorageClass(headers, isObs) 522 if input.Metadata != nil { 523 for key, value := range input.Metadata { 524 key = strings.TrimSpace(key) 525 setHeadersNext(headers, HEADER_PREFIX_META_OBS+key, HEADER_PREFIX_META+key, []string{value}, isObs) 526 } 527 } 528 return 529 } 530 531 func (input GetObjectInput) prepareResponseParams(params map[string]string) { 532 if input.ResponseCacheControl != "" { 533 params[PARAM_RESPONSE_CACHE_CONTROL] = input.ResponseCacheControl 534 } 535 if input.ResponseContentDisposition != "" { 536 params[PARAM_RESPONSE_CONTENT_DISPOSITION] = input.ResponseContentDisposition 537 } 538 if input.ResponseContentEncoding != "" { 539 params[PARAM_RESPONSE_CONTENT_ENCODING] = input.ResponseContentEncoding 540 } 541 if input.ResponseContentLanguage != "" { 542 params[PARAM_RESPONSE_CONTENT_LANGUAGE] = input.ResponseContentLanguage 543 } 544 if input.ResponseContentType != "" { 545 params[PARAM_RESPONSE_CONTENT_TYPE] = input.ResponseContentType 546 } 547 if input.ResponseExpires != "" { 548 params[PARAM_RESPONSE_EXPIRES] = input.ResponseExpires 549 } 550 } 551 552 func (input GetObjectInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 553 params, headers, data, err = input.GetObjectMetadataInput.trans(isObs) 554 if err != nil { 555 return 556 } 557 input.prepareResponseParams(params) 558 if input.ImageProcess != "" { 559 params[PARAM_IMAGE_PROCESS] = input.ImageProcess 560 } 561 if input.RangeStart >= 0 && input.RangeEnd > input.RangeStart { 562 headers[HEADER_RANGE] = []string{fmt.Sprintf("bytes=%d-%d", input.RangeStart, input.RangeEnd)} 563 } 564 565 if input.IfMatch != "" { 566 headers[HEADER_IF_MATCH] = []string{input.IfMatch} 567 } 568 if input.IfNoneMatch != "" { 569 headers[HEADER_IF_NONE_MATCH] = []string{input.IfNoneMatch} 570 } 571 if !input.IfModifiedSince.IsZero() { 572 headers[HEADER_IF_MODIFIED_SINCE] = []string{FormatUtcToRfc1123(input.IfModifiedSince)} 573 } 574 if !input.IfUnmodifiedSince.IsZero() { 575 headers[HEADER_IF_UNMODIFIED_SINCE] = []string{FormatUtcToRfc1123(input.IfUnmodifiedSince)} 576 } 577 return 578 } 579 580 func (input ObjectOperationInput) prepareGrantHeaders(headers map[string][]string) { 581 if GrantReadId := input.GrantReadId; GrantReadId != "" { 582 setHeaders(headers, HEADER_GRANT_READ_OBS, []string{GrantReadId}, true) 583 } 584 if GrantReadAcpId := input.GrantReadAcpId; GrantReadAcpId != "" { 585 setHeaders(headers, HEADER_GRANT_READ_ACP_OBS, []string{GrantReadAcpId}, true) 586 } 587 if GrantWriteAcpId := input.GrantWriteAcpId; GrantWriteAcpId != "" { 588 setHeaders(headers, HEADER_GRANT_WRITE_ACP_OBS, []string{GrantWriteAcpId}, true) 589 } 590 if GrantFullControlId := input.GrantFullControlId; GrantFullControlId != "" { 591 setHeaders(headers, HEADER_GRANT_FULL_CONTROL_OBS, []string{GrantFullControlId}, true) 592 } 593 } 594 595 func (input ObjectOperationInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 596 headers = make(map[string][]string) 597 params = make(map[string]string) 598 if acl := string(input.ACL); acl != "" { 599 setHeaders(headers, HEADER_ACL, []string{acl}, isObs) 600 } 601 input.prepareGrantHeaders(headers) 602 if storageClass := string(input.StorageClass); storageClass != "" { 603 if !isObs { 604 if storageClass == string(StorageClassWarm) { 605 storageClass = string(storageClassStandardIA) 606 } else if storageClass == string(StorageClassCold) { 607 storageClass = string(storageClassGlacier) 608 } 609 } 610 setHeaders(headers, HEADER_STORAGE_CLASS2, []string{storageClass}, isObs) 611 } 612 if input.WebsiteRedirectLocation != "" { 613 setHeaders(headers, HEADER_WEBSITE_REDIRECT_LOCATION, []string{input.WebsiteRedirectLocation}, isObs) 614 615 } 616 setSseHeader(headers, input.SseHeader, false, isObs) 617 if input.Expires != 0 { 618 setHeaders(headers, HEADER_EXPIRES, []string{Int64ToString(input.Expires)}, true) 619 } 620 if input.Metadata != nil { 621 for key, value := range input.Metadata { 622 key = strings.TrimSpace(key) 623 setHeadersNext(headers, HEADER_PREFIX_META_OBS+key, HEADER_PREFIX_META+key, []string{value}, isObs) 624 } 625 } 626 return 627 } 628 629 func (input PutObjectBasicInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 630 params, headers, data, err = input.ObjectOperationInput.trans(isObs) 631 if err != nil { 632 return 633 } 634 635 if input.ContentMD5 != "" { 636 headers[HEADER_MD5_CAMEL] = []string{input.ContentMD5} 637 } 638 639 if input.ContentLength > 0 { 640 headers[HEADER_CONTENT_LENGTH_CAMEL] = []string{Int64ToString(input.ContentLength)} 641 } 642 if input.ContentType != "" { 643 headers[HEADER_CONTENT_TYPE_CAML] = []string{input.ContentType} 644 } 645 646 return 647 } 648 649 func (input PutObjectInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 650 params, headers, data, err = input.PutObjectBasicInput.trans(isObs) 651 if err != nil { 652 return 653 } 654 if input.Body != nil { 655 data = input.Body 656 } 657 return 658 } 659 660 func (input CopyObjectInput) prepareReplaceHeaders(headers map[string][]string) { 661 if input.CacheControl != "" { 662 headers[HEADER_CACHE_CONTROL] = []string{input.CacheControl} 663 } 664 if input.ContentDisposition != "" { 665 headers[HEADER_CONTENT_DISPOSITION] = []string{input.ContentDisposition} 666 } 667 if input.ContentEncoding != "" { 668 headers[HEADER_CONTENT_ENCODING] = []string{input.ContentEncoding} 669 } 670 if input.ContentLanguage != "" { 671 headers[HEADER_CONTENT_LANGUAGE] = []string{input.ContentLanguage} 672 } 673 if input.ContentType != "" { 674 headers[HEADER_CONTENT_TYPE] = []string{input.ContentType} 675 } 676 if input.Expires != "" { 677 headers[HEADER_EXPIRES] = []string{input.Expires} 678 } 679 } 680 681 func (input CopyObjectInput) prepareCopySourceHeaders(headers map[string][]string, isObs bool) { 682 if input.CopySourceIfMatch != "" { 683 setHeaders(headers, HEADER_COPY_SOURCE_IF_MATCH, []string{input.CopySourceIfMatch}, isObs) 684 } 685 if input.CopySourceIfNoneMatch != "" { 686 setHeaders(headers, HEADER_COPY_SOURCE_IF_NONE_MATCH, []string{input.CopySourceIfNoneMatch}, isObs) 687 } 688 if !input.CopySourceIfModifiedSince.IsZero() { 689 setHeaders(headers, HEADER_COPY_SOURCE_IF_MODIFIED_SINCE, []string{FormatUtcToRfc1123(input.CopySourceIfModifiedSince)}, isObs) 690 } 691 if !input.CopySourceIfUnmodifiedSince.IsZero() { 692 setHeaders(headers, HEADER_COPY_SOURCE_IF_UNMODIFIED_SINCE, []string{FormatUtcToRfc1123(input.CopySourceIfUnmodifiedSince)}, isObs) 693 } 694 } 695 696 func (input CopyObjectInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 697 params, headers, data, err = input.ObjectOperationInput.trans(isObs) 698 if err != nil { 699 return 700 } 701 702 var copySource string 703 if input.CopySourceVersionId != "" { 704 copySource = fmt.Sprintf("%s/%s?versionId=%s", input.CopySourceBucket, UrlEncode(input.CopySourceKey, false), input.CopySourceVersionId) 705 } else { 706 copySource = fmt.Sprintf("%s/%s", input.CopySourceBucket, UrlEncode(input.CopySourceKey, false)) 707 } 708 setHeaders(headers, HEADER_COPY_SOURCE, []string{copySource}, isObs) 709 710 if directive := string(input.MetadataDirective); directive != "" { 711 setHeaders(headers, HEADER_METADATA_DIRECTIVE, []string{directive}, isObs) 712 } 713 714 if input.MetadataDirective == ReplaceMetadata { 715 input.prepareReplaceHeaders(headers) 716 } 717 718 input.prepareCopySourceHeaders(headers, isObs) 719 if input.SourceSseHeader != nil { 720 if sseCHeader, ok := input.SourceSseHeader.(SseCHeader); ok { 721 setHeaders(headers, HEADER_SSEC_COPY_SOURCE_ENCRYPTION, []string{sseCHeader.GetEncryption()}, isObs) 722 setHeaders(headers, HEADER_SSEC_COPY_SOURCE_KEY, []string{sseCHeader.GetKey()}, isObs) 723 setHeaders(headers, HEADER_SSEC_COPY_SOURCE_KEY_MD5, []string{sseCHeader.GetKeyMD5()}, isObs) 724 } 725 } 726 if input.SuccessActionRedirect != "" { 727 headers[HEADER_SUCCESS_ACTION_REDIRECT] = []string{input.SuccessActionRedirect} 728 } 729 return 730 } 731 732 func (input AbortMultipartUploadInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 733 params = map[string]string{"uploadId": input.UploadId} 734 return 735 } 736 737 func (input InitiateMultipartUploadInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 738 params, headers, data, err = input.ObjectOperationInput.trans(isObs) 739 if err != nil { 740 return 741 } 742 if input.ContentType != "" { 743 headers[HEADER_CONTENT_TYPE_CAML] = []string{input.ContentType} 744 } 745 params[string(SubResourceUploads)] = "" 746 return 747 } 748 749 func (input UploadPartInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 750 params = map[string]string{"uploadId": input.UploadId, "partNumber": IntToString(input.PartNumber)} 751 headers = make(map[string][]string) 752 setSseHeader(headers, input.SseHeader, true, isObs) 753 if input.ContentMD5 != "" { 754 headers[HEADER_MD5_CAMEL] = []string{input.ContentMD5} 755 } 756 if input.Body != nil { 757 data = input.Body 758 } 759 return 760 } 761 762 func (input CompleteMultipartUploadInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 763 params = map[string]string{"uploadId": input.UploadId} 764 data, _ = ConvertCompleteMultipartUploadInputToXml(input, false) 765 return 766 } 767 768 func (input ListPartsInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 769 params = map[string]string{"uploadId": input.UploadId} 770 if input.MaxParts > 0 { 771 params["max-parts"] = IntToString(input.MaxParts) 772 } 773 if input.PartNumberMarker > 0 { 774 params["part-number-marker"] = IntToString(input.PartNumberMarker) 775 } 776 return 777 } 778 779 func (input CopyPartInput) trans(isObs bool) (params map[string]string, headers map[string][]string, data interface{}, err error) { 780 params = map[string]string{"uploadId": input.UploadId, "partNumber": IntToString(input.PartNumber)} 781 headers = make(map[string][]string, 1) 782 var copySource string 783 if input.CopySourceVersionId != "" { 784 copySource = fmt.Sprintf("%s/%s?versionId=%s", input.CopySourceBucket, UrlEncode(input.CopySourceKey, false), input.CopySourceVersionId) 785 } else { 786 copySource = fmt.Sprintf("%s/%s", input.CopySourceBucket, UrlEncode(input.CopySourceKey, false)) 787 } 788 setHeaders(headers, HEADER_COPY_SOURCE, []string{copySource}, isObs) 789 if input.CopySourceRangeStart >= 0 && input.CopySourceRangeEnd > input.CopySourceRangeStart { 790 setHeaders(headers, HEADER_COPY_SOURCE_RANGE, []string{fmt.Sprintf("bytes=%d-%d", input.CopySourceRangeStart, input.CopySourceRangeEnd)}, isObs) 791 } 792 793 setSseHeader(headers, input.SseHeader, true, isObs) 794 if input.SourceSseHeader != nil { 795 if sseCHeader, ok := input.SourceSseHeader.(SseCHeader); ok { 796 setHeaders(headers, HEADER_SSEC_COPY_SOURCE_ENCRYPTION, []string{sseCHeader.GetEncryption()}, isObs) 797 setHeaders(headers, HEADER_SSEC_COPY_SOURCE_KEY, []string{sseCHeader.GetKey()}, isObs) 798 setHeaders(headers, HEADER_SSEC_COPY_SOURCE_KEY_MD5, []string{sseCHeader.GetKeyMD5()}, isObs) 799 } 800 801 } 802 return 803 } 804 805 type partSlice []Part 806 807 func (parts partSlice) Len() int { 808 return len(parts) 809 } 810 811 func (parts partSlice) Less(i, j int) bool { 812 return parts[i].PartNumber < parts[j].PartNumber 813 } 814 815 func (parts partSlice) Swap(i, j int) { 816 parts[i], parts[j] = parts[j], parts[i] 817 } 818 819 type readerWrapper struct { 820 reader io.Reader 821 mark int64 822 totalCount int64 823 readedCount int64 824 } 825 826 func (rw *readerWrapper) seek(offset int64, whence int) (int64, error) { 827 if r, ok := rw.reader.(*strings.Reader); ok { 828 return r.Seek(offset, whence) 829 } else if r, ok := rw.reader.(*bytes.Reader); ok { 830 return r.Seek(offset, whence) 831 } else if r, ok := rw.reader.(*os.File); ok { 832 return r.Seek(offset, whence) 833 } 834 return offset, nil 835 } 836 837 func (rw *readerWrapper) Read(p []byte) (n int, err error) { 838 if rw.totalCount == 0 { 839 return 0, io.EOF 840 } 841 if rw.totalCount > 0 { 842 n, err = rw.reader.Read(p) 843 readedOnce := int64(n) 844 remainCount := rw.totalCount - rw.readedCount 845 if remainCount > readedOnce { 846 rw.readedCount += readedOnce 847 return n, err 848 } 849 rw.readedCount += remainCount 850 return int(remainCount), io.EOF 851 } 852 return rw.reader.Read(p) 853 } 854 855 type fileReaderWrapper struct { 856 readerWrapper 857 filePath string 858 }