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