yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/huawei/obs/convert.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 "io/ioutil" 34 "net/http" 35 "reflect" 36 "strings" 37 "time" 38 ) 39 40 func cleanHeaderPrefix(header http.Header) map[string][]string { 41 responseHeaders := make(map[string][]string) 42 for key, value := range header { 43 if len(value) > 0 { 44 key = strings.ToLower(key) 45 if strings.HasPrefix(key, HEADER_PREFIX) || strings.HasPrefix(key, HEADER_PREFIX_OBS) { 46 key = key[len(HEADER_PREFIX):] 47 } 48 responseHeaders[key] = value 49 } 50 } 51 return responseHeaders 52 } 53 54 func ParseStringToEventType(value string) (ret EventType) { 55 switch value { 56 case "ObjectCreated:*", "s3:ObjectCreated:*": 57 ret = ObjectCreatedAll 58 case "ObjectCreated:Put", "s3:ObjectCreated:Put": 59 ret = ObjectCreatedPut 60 case "ObjectCreated:Post", "s3:ObjectCreated:Post": 61 ret = ObjectCreatedPost 62 case "ObjectCreated:Copy", "s3:ObjectCreated:Copy": 63 ret = ObjectCreatedCopy 64 case "ObjectCreated:CompleteMultipartUpload", "s3:ObjectCreated:CompleteMultipartUpload": 65 ret = ObjectCreatedCompleteMultipartUpload 66 case "ObjectRemoved:*", "s3:ObjectRemoved:*": 67 ret = ObjectRemovedAll 68 case "ObjectRemoved:Delete", "s3:ObjectRemoved:Delete": 69 ret = ObjectRemovedDelete 70 case "ObjectRemoved:DeleteMarkerCreated", "s3:ObjectRemoved:DeleteMarkerCreated": 71 ret = ObjectRemovedDeleteMarkerCreated 72 default: 73 ret = "" 74 } 75 return 76 } 77 78 func ParseStringToStorageClassType(value string) (ret StorageClassType) { 79 switch value { 80 case "STANDARD": 81 ret = StorageClassStandard 82 case "STANDARD_IA", "WARM": 83 ret = StorageClassWarm 84 case "GLACIER", "COLD": 85 ret = StorageClassCold 86 default: 87 ret = "" 88 } 89 return 90 } 91 92 func prepareGrantURI(grant Grant) string { 93 if grant.Grantee.URI == GroupAllUsers || grant.Grantee.URI == GroupAuthenticatedUsers { 94 return fmt.Sprintf("<URI>%s%s</URI>", "http://acs.amazonaws.com/groups/global/", grant.Grantee.URI) 95 } 96 if grant.Grantee.URI == GroupLogDelivery { 97 return fmt.Sprintf("<URI>%s%s</URI>", "http://acs.amazonaws.com/groups/s3/", grant.Grantee.URI) 98 } 99 return fmt.Sprintf("<URI>%s</URI>", grant.Grantee.URI) 100 } 101 102 func convertGrantToXml(grant Grant, isObs bool, isBucket bool) string { 103 xml := make([]string, 0, 4) 104 105 if grant.Grantee.Type == GranteeUser { 106 if isObs { 107 xml = append(xml, "<Grant><Grantee>") 108 } else { 109 xml = append(xml, fmt.Sprintf("<Grant><Grantee xsi:type=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", grant.Grantee.Type)) 110 } 111 if grant.Grantee.ID != "" { 112 granteeID := XmlTranscoding(grant.Grantee.ID) 113 xml = append(xml, fmt.Sprintf("<ID>%s</ID>", granteeID)) 114 } 115 if !isObs && grant.Grantee.DisplayName != "" { 116 granteeDisplayName := XmlTranscoding(grant.Grantee.DisplayName) 117 xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", granteeDisplayName)) 118 } 119 xml = append(xml, "</Grantee>") 120 } else { 121 if !isObs { 122 xml = append(xml, fmt.Sprintf("<Grant><Grantee xsi:type=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", grant.Grantee.Type)) 123 xml = append(xml, prepareGrantURI(grant)) 124 xml = append(xml, "</Grantee>") 125 } else if grant.Grantee.URI == GroupAllUsers { 126 xml = append(xml, "<Grant><Grantee>") 127 xml = append(xml, fmt.Sprintf("<Canned>Everyone</Canned>")) 128 xml = append(xml, "</Grantee>") 129 } else { 130 return strings.Join(xml, "") 131 } 132 } 133 134 xml = append(xml, fmt.Sprintf("<Permission>%s</Permission>", grant.Permission)) 135 if isObs && isBucket { 136 xml = append(xml, fmt.Sprintf("<Delivered>%t</Delivered>", grant.Delivered)) 137 } 138 xml = append(xml, fmt.Sprintf("</Grant>")) 139 return strings.Join(xml, "") 140 } 141 142 func hasLoggingTarget(input BucketLoggingStatus) bool { 143 if input.TargetBucket != "" || input.TargetPrefix != "" || len(input.TargetGrants) > 0 { 144 return true 145 } 146 return false 147 } 148 149 func ConvertLoggingStatusToXml(input BucketLoggingStatus, returnMd5 bool, isObs bool) (data string, md5 string) { 150 grantsLength := len(input.TargetGrants) 151 xml := make([]string, 0, 8+grantsLength) 152 153 xml = append(xml, "<BucketLoggingStatus>") 154 if isObs && input.Agency != "" { 155 agency := XmlTranscoding(input.Agency) 156 xml = append(xml, fmt.Sprintf("<Agency>%s</Agency>", agency)) 157 } 158 if hasLoggingTarget(input) { 159 xml = append(xml, "<LoggingEnabled>") 160 if input.TargetBucket != "" { 161 xml = append(xml, fmt.Sprintf("<TargetBucket>%s</TargetBucket>", input.TargetBucket)) 162 } 163 if input.TargetPrefix != "" { 164 targetPrefix := XmlTranscoding(input.TargetPrefix) 165 xml = append(xml, fmt.Sprintf("<TargetPrefix>%s</TargetPrefix>", targetPrefix)) 166 } 167 if grantsLength > 0 { 168 xml = append(xml, "<TargetGrants>") 169 for _, grant := range input.TargetGrants { 170 xml = append(xml, convertGrantToXml(grant, isObs, false)) 171 } 172 xml = append(xml, "</TargetGrants>") 173 } 174 175 xml = append(xml, "</LoggingEnabled>") 176 } 177 xml = append(xml, "</BucketLoggingStatus>") 178 data = strings.Join(xml, "") 179 if returnMd5 { 180 md5 = Base64Md5([]byte(data)) 181 } 182 return 183 } 184 185 func ConvertAclToXml(input AccessControlPolicy, returnMd5 bool, isObs bool) (data string, md5 string) { 186 xml := make([]string, 0, 4+len(input.Grants)) 187 ownerID := XmlTranscoding(input.Owner.ID) 188 xml = append(xml, fmt.Sprintf("<AccessControlPolicy><Owner><ID>%s</ID>", ownerID)) 189 if !isObs && input.Owner.DisplayName != "" { 190 ownerDisplayName := XmlTranscoding(input.Owner.DisplayName) 191 xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", ownerDisplayName)) 192 } 193 if isObs && input.Delivered != "" { 194 objectDelivered := XmlTranscoding(input.Delivered) 195 xml = append(xml, fmt.Sprintf("</Owner><Delivered>%s</Delivered><AccessControlList>", objectDelivered)) 196 } else { 197 xml = append(xml, "</Owner><AccessControlList>") 198 } 199 for _, grant := range input.Grants { 200 xml = append(xml, convertGrantToXml(grant, isObs, false)) 201 } 202 xml = append(xml, "</AccessControlList></AccessControlPolicy>") 203 data = strings.Join(xml, "") 204 if returnMd5 { 205 md5 = Base64Md5([]byte(data)) 206 } 207 return 208 } 209 210 func convertBucketAclToXml(input AccessControlPolicy, returnMd5 bool, isObs bool) (data string, md5 string) { 211 xml := make([]string, 0, 4+len(input.Grants)) 212 ownerID := XmlTranscoding(input.Owner.ID) 213 xml = append(xml, fmt.Sprintf("<AccessControlPolicy><Owner><ID>%s</ID>", ownerID)) 214 if !isObs && input.Owner.DisplayName != "" { 215 ownerDisplayName := XmlTranscoding(input.Owner.DisplayName) 216 xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", ownerDisplayName)) 217 } 218 219 xml = append(xml, "</Owner><AccessControlList>") 220 221 for _, grant := range input.Grants { 222 xml = append(xml, convertGrantToXml(grant, isObs, true)) 223 } 224 xml = append(xml, "</AccessControlList></AccessControlPolicy>") 225 data = strings.Join(xml, "") 226 if returnMd5 { 227 md5 = Base64Md5([]byte(data)) 228 } 229 return 230 } 231 232 func convertConditionToXml(condition Condition) string { 233 xml := make([]string, 0, 2) 234 if condition.KeyPrefixEquals != "" { 235 keyPrefixEquals := XmlTranscoding(condition.KeyPrefixEquals) 236 xml = append(xml, fmt.Sprintf("<KeyPrefixEquals>%s</KeyPrefixEquals>", keyPrefixEquals)) 237 } 238 if condition.HttpErrorCodeReturnedEquals != "" { 239 xml = append(xml, fmt.Sprintf("<HttpErrorCodeReturnedEquals>%s</HttpErrorCodeReturnedEquals>", condition.HttpErrorCodeReturnedEquals)) 240 } 241 if len(xml) > 0 { 242 return fmt.Sprintf("<Condition>%s</Condition>", strings.Join(xml, "")) 243 } 244 return "" 245 } 246 247 func prepareRoutingRule(input BucketWebsiteConfiguration) string { 248 xml := make([]string, 0, len(input.RoutingRules)*10) 249 for _, routingRule := range input.RoutingRules { 250 xml = append(xml, "<RoutingRule>") 251 xml = append(xml, "<Redirect>") 252 if routingRule.Redirect.Protocol != "" { 253 xml = append(xml, fmt.Sprintf("<Protocol>%s</Protocol>", routingRule.Redirect.Protocol)) 254 } 255 if routingRule.Redirect.HostName != "" { 256 xml = append(xml, fmt.Sprintf("<HostName>%s</HostName>", routingRule.Redirect.HostName)) 257 } 258 if routingRule.Redirect.ReplaceKeyPrefixWith != "" { 259 replaceKeyPrefixWith := XmlTranscoding(routingRule.Redirect.ReplaceKeyPrefixWith) 260 xml = append(xml, fmt.Sprintf("<ReplaceKeyPrefixWith>%s</ReplaceKeyPrefixWith>", replaceKeyPrefixWith)) 261 } 262 263 if routingRule.Redirect.ReplaceKeyWith != "" { 264 replaceKeyWith := XmlTranscoding(routingRule.Redirect.ReplaceKeyWith) 265 xml = append(xml, fmt.Sprintf("<ReplaceKeyWith>%s</ReplaceKeyWith>", replaceKeyWith)) 266 } 267 if routingRule.Redirect.HttpRedirectCode != "" { 268 xml = append(xml, fmt.Sprintf("<HttpRedirectCode>%s</HttpRedirectCode>", routingRule.Redirect.HttpRedirectCode)) 269 } 270 xml = append(xml, "</Redirect>") 271 272 if ret := convertConditionToXml(routingRule.Condition); ret != "" { 273 xml = append(xml, ret) 274 } 275 xml = append(xml, "</RoutingRule>") 276 } 277 return strings.Join(xml, "") 278 } 279 280 func ConvertWebsiteConfigurationToXml(input BucketWebsiteConfiguration, returnMd5 bool) (data string, md5 string) { 281 routingRuleLength := len(input.RoutingRules) 282 xml := make([]string, 0, 6+routingRuleLength*10) 283 xml = append(xml, "<WebsiteConfiguration>") 284 285 if input.RedirectAllRequestsTo.HostName != "" { 286 xml = append(xml, fmt.Sprintf("<RedirectAllRequestsTo><HostName>%s</HostName>", input.RedirectAllRequestsTo.HostName)) 287 if input.RedirectAllRequestsTo.Protocol != "" { 288 xml = append(xml, fmt.Sprintf("<Protocol>%s</Protocol>", input.RedirectAllRequestsTo.Protocol)) 289 } 290 xml = append(xml, "</RedirectAllRequestsTo>") 291 } else { 292 if input.IndexDocument.Suffix != "" { 293 indexDocumentSuffix := XmlTranscoding(input.IndexDocument.Suffix) 294 xml = append(xml, fmt.Sprintf("<IndexDocument><Suffix>%s</Suffix></IndexDocument>", indexDocumentSuffix)) 295 } 296 if input.ErrorDocument.Key != "" { 297 errorDocumentKey := XmlTranscoding(input.ErrorDocument.Key) 298 xml = append(xml, fmt.Sprintf("<ErrorDocument><Key>%s</Key></ErrorDocument>", errorDocumentKey)) 299 } 300 if routingRuleLength > 0 { 301 xml = append(xml, "<RoutingRules>") 302 xml = append(xml, prepareRoutingRule(input)) 303 xml = append(xml, "</RoutingRules>") 304 } 305 } 306 307 xml = append(xml, "</WebsiteConfiguration>") 308 data = strings.Join(xml, "") 309 if returnMd5 { 310 md5 = Base64Md5([]byte(data)) 311 } 312 return 313 } 314 315 func convertTransitionsToXml(transitions []Transition, isObs bool) string { 316 if length := len(transitions); length > 0 { 317 xml := make([]string, 0, length) 318 for _, transition := range transitions { 319 var temp string 320 if transition.Days > 0 { 321 temp = fmt.Sprintf("<Days>%d</Days>", transition.Days) 322 } else if !transition.Date.IsZero() { 323 temp = fmt.Sprintf("<Date>%s</Date>", transition.Date.UTC().Format(ISO8601_MIDNIGHT_DATE_FORMAT)) 324 } 325 if temp != "" { 326 if !isObs { 327 storageClass := string(transition.StorageClass) 328 if transition.StorageClass == StorageClassWarm { 329 storageClass = string(storageClassStandardIA) 330 } else if transition.StorageClass == StorageClassCold { 331 storageClass = string(storageClassGlacier) 332 } 333 xml = append(xml, fmt.Sprintf("<Transition>%s<StorageClass>%s</StorageClass></Transition>", temp, storageClass)) 334 } else { 335 xml = append(xml, fmt.Sprintf("<Transition>%s<StorageClass>%s</StorageClass></Transition>", temp, transition.StorageClass)) 336 } 337 } 338 } 339 return strings.Join(xml, "") 340 } 341 return "" 342 } 343 344 func convertExpirationToXml(expiration Expiration) string { 345 if expiration.Days > 0 { 346 return fmt.Sprintf("<Expiration><Days>%d</Days></Expiration>", expiration.Days) 347 } else if !expiration.Date.IsZero() { 348 return fmt.Sprintf("<Expiration><Date>%s</Date></Expiration>", expiration.Date.UTC().Format(ISO8601_MIDNIGHT_DATE_FORMAT)) 349 } 350 return "" 351 } 352 func convertNoncurrentVersionTransitionsToXml(noncurrentVersionTransitions []NoncurrentVersionTransition, isObs bool) string { 353 if length := len(noncurrentVersionTransitions); length > 0 { 354 xml := make([]string, 0, length) 355 for _, noncurrentVersionTransition := range noncurrentVersionTransitions { 356 if noncurrentVersionTransition.NoncurrentDays > 0 { 357 storageClass := string(noncurrentVersionTransition.StorageClass) 358 if !isObs { 359 if storageClass == string(StorageClassWarm) { 360 storageClass = string(storageClassStandardIA) 361 } else if storageClass == string(StorageClassCold) { 362 storageClass = string(storageClassGlacier) 363 } 364 } 365 xml = append(xml, fmt.Sprintf("<NoncurrentVersionTransition><NoncurrentDays>%d</NoncurrentDays>"+ 366 "<StorageClass>%s</StorageClass></NoncurrentVersionTransition>", 367 noncurrentVersionTransition.NoncurrentDays, storageClass)) 368 } 369 } 370 return strings.Join(xml, "") 371 } 372 return "" 373 } 374 func convertNoncurrentVersionExpirationToXml(noncurrentVersionExpiration NoncurrentVersionExpiration) string { 375 if noncurrentVersionExpiration.NoncurrentDays > 0 { 376 return fmt.Sprintf("<NoncurrentVersionExpiration><NoncurrentDays>%d</NoncurrentDays></NoncurrentVersionExpiration>", noncurrentVersionExpiration.NoncurrentDays) 377 } 378 return "" 379 } 380 381 func ConvertLifecyleConfigurationToXml(input BucketLifecyleConfiguration, returnMd5 bool, isObs bool) (data string, md5 string) { 382 xml := make([]string, 0, 2+len(input.LifecycleRules)*9) 383 xml = append(xml, "<LifecycleConfiguration>") 384 for _, lifecyleRule := range input.LifecycleRules { 385 xml = append(xml, "<Rule>") 386 if lifecyleRule.ID != "" { 387 lifecyleRuleID := XmlTranscoding(lifecyleRule.ID) 388 xml = append(xml, fmt.Sprintf("<ID>%s</ID>", lifecyleRuleID)) 389 } 390 lifecyleRulePrefix := XmlTranscoding(lifecyleRule.Prefix) 391 xml = append(xml, fmt.Sprintf("<Prefix>%s</Prefix>", lifecyleRulePrefix)) 392 xml = append(xml, fmt.Sprintf("<Status>%s</Status>", lifecyleRule.Status)) 393 if ret := convertTransitionsToXml(lifecyleRule.Transitions, isObs); ret != "" { 394 xml = append(xml, ret) 395 } 396 if ret := convertExpirationToXml(lifecyleRule.Expiration); ret != "" { 397 xml = append(xml, ret) 398 } 399 if ret := convertNoncurrentVersionTransitionsToXml(lifecyleRule.NoncurrentVersionTransitions, isObs); ret != "" { 400 xml = append(xml, ret) 401 } 402 if ret := convertNoncurrentVersionExpirationToXml(lifecyleRule.NoncurrentVersionExpiration); ret != "" { 403 xml = append(xml, ret) 404 } 405 xml = append(xml, "</Rule>") 406 } 407 xml = append(xml, "</LifecycleConfiguration>") 408 data = strings.Join(xml, "") 409 if returnMd5 { 410 md5 = Base64Md5([]byte(data)) 411 } 412 return 413 } 414 415 func converntFilterRulesToXml(filterRules []FilterRule, isObs bool) string { 416 if length := len(filterRules); length > 0 { 417 xml := make([]string, 0, length*4) 418 for _, filterRule := range filterRules { 419 xml = append(xml, "<FilterRule>") 420 if filterRule.Name != "" { 421 filterRuleName := XmlTranscoding(filterRule.Name) 422 xml = append(xml, fmt.Sprintf("<Name>%s</Name>", filterRuleName)) 423 } 424 if filterRule.Value != "" { 425 filterRuleValue := XmlTranscoding(filterRule.Value) 426 xml = append(xml, fmt.Sprintf("<Value>%s</Value>", filterRuleValue)) 427 } 428 xml = append(xml, "</FilterRule>") 429 } 430 if !isObs { 431 return fmt.Sprintf("<Filter><S3Key>%s</S3Key></Filter>", strings.Join(xml, "")) 432 } 433 return fmt.Sprintf("<Filter><Object>%s</Object></Filter>", strings.Join(xml, "")) 434 } 435 return "" 436 } 437 438 func converntEventsToXml(events []EventType, isObs bool) string { 439 if length := len(events); length > 0 { 440 xml := make([]string, 0, length) 441 if !isObs { 442 for _, event := range events { 443 xml = append(xml, fmt.Sprintf("<Event>%s%s</Event>", "s3:", event)) 444 } 445 } else { 446 for _, event := range events { 447 xml = append(xml, fmt.Sprintf("<Event>%s</Event>", event)) 448 } 449 } 450 return strings.Join(xml, "") 451 } 452 return "" 453 } 454 455 func converntConfigureToXml(topicConfiguration TopicConfiguration, xmlElem string, isObs bool) string { 456 xml := make([]string, 0, 6) 457 xml = append(xml, xmlElem) 458 if topicConfiguration.ID != "" { 459 topicConfigurationID := XmlTranscoding(topicConfiguration.ID) 460 xml = append(xml, fmt.Sprintf("<Id>%s</Id>", topicConfigurationID)) 461 } 462 topicConfigurationTopic := XmlTranscoding(topicConfiguration.Topic) 463 xml = append(xml, fmt.Sprintf("<Topic>%s</Topic>", topicConfigurationTopic)) 464 465 if ret := converntEventsToXml(topicConfiguration.Events, isObs); ret != "" { 466 xml = append(xml, ret) 467 } 468 if ret := converntFilterRulesToXml(topicConfiguration.FilterRules, isObs); ret != "" { 469 xml = append(xml, ret) 470 } 471 tempElem := xmlElem[0:1] + "/" + xmlElem[1:] 472 xml = append(xml, tempElem) 473 return strings.Join(xml, "") 474 } 475 476 func ConverntObsRestoreToXml(restoreObjectInput RestoreObjectInput) string { 477 xml := make([]string, 0, 2) 478 xml = append(xml, fmt.Sprintf("<RestoreRequest><Days>%d</Days>", restoreObjectInput.Days)) 479 if restoreObjectInput.Tier != "Bulk" { 480 xml = append(xml, fmt.Sprintf("<RestoreJob><Tier>%s</Tier></RestoreJob>", restoreObjectInput.Tier)) 481 } 482 xml = append(xml, fmt.Sprintf("</RestoreRequest>")) 483 data := strings.Join(xml, "") 484 return data 485 } 486 487 func ConvertNotificationToXml(input BucketNotification, returnMd5 bool, isObs bool) (data string, md5 string) { 488 xml := make([]string, 0, 2+len(input.TopicConfigurations)*6) 489 xml = append(xml, "<NotificationConfiguration>") 490 for _, topicConfiguration := range input.TopicConfigurations { 491 ret := converntConfigureToXml(topicConfiguration, "<TopicConfiguration>", isObs) 492 xml = append(xml, ret) 493 } 494 xml = append(xml, "</NotificationConfiguration>") 495 data = strings.Join(xml, "") 496 if returnMd5 { 497 md5 = Base64Md5([]byte(data)) 498 } 499 return 500 } 501 502 func ConvertCompleteMultipartUploadInputToXml(input CompleteMultipartUploadInput, returnMd5 bool) (data string, md5 string) { 503 xml := make([]string, 0, 2+len(input.Parts)*4) 504 xml = append(xml, "<CompleteMultipartUpload>") 505 for _, part := range input.Parts { 506 xml = append(xml, "<Part>") 507 xml = append(xml, fmt.Sprintf("<PartNumber>%d</PartNumber>", part.PartNumber)) 508 xml = append(xml, fmt.Sprintf("<ETag>%s</ETag>", part.ETag)) 509 xml = append(xml, "</Part>") 510 } 511 xml = append(xml, "</CompleteMultipartUpload>") 512 data = strings.Join(xml, "") 513 if returnMd5 { 514 md5 = Base64Md5([]byte(data)) 515 } 516 return 517 } 518 519 func parseSseHeader(responseHeaders map[string][]string) (sseHeader ISseHeader) { 520 if ret, ok := responseHeaders[HEADER_SSEC_ENCRYPTION]; ok { 521 sseCHeader := SseCHeader{Encryption: ret[0]} 522 if ret, ok = responseHeaders[HEADER_SSEC_KEY_MD5]; ok { 523 sseCHeader.KeyMD5 = ret[0] 524 } 525 sseHeader = sseCHeader 526 } else if ret, ok := responseHeaders[HEADER_SSEKMS_ENCRYPTION]; ok { 527 sseKmsHeader := SseKmsHeader{Encryption: ret[0]} 528 if ret, ok = responseHeaders[HEADER_SSEKMS_KEY]; ok { 529 sseKmsHeader.Key = ret[0] 530 } else if ret, ok = responseHeaders[HEADER_SSEKMS_ENCRYPT_KEY_OBS]; ok { 531 sseKmsHeader.Key = ret[0] 532 } 533 sseHeader = sseKmsHeader 534 } 535 return 536 } 537 538 func parseCorsHeader(output BaseModel) (AllowOrigin, AllowHeader, AllowMethod, ExposeHeader string, MaxAgeSeconds int) { 539 if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_ORIGIN]; ok { 540 AllowOrigin = ret[0] 541 } 542 if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_HEADERS]; ok { 543 AllowHeader = ret[0] 544 } 545 if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_MAX_AGE]; ok { 546 MaxAgeSeconds = StringToInt(ret[0], 0) 547 } 548 if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_METHODS]; ok { 549 AllowMethod = ret[0] 550 } 551 if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_EXPOSE_HEADERS]; ok { 552 ExposeHeader = ret[0] 553 } 554 return 555 } 556 557 func parseUnCommonHeader(output *GetObjectMetadataOutput) { 558 if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok { 559 output.VersionId = ret[0] 560 } 561 if ret, ok := output.ResponseHeaders[HEADER_WEBSITE_REDIRECT_LOCATION]; ok { 562 output.WebsiteRedirectLocation = ret[0] 563 } 564 if ret, ok := output.ResponseHeaders[HEADER_EXPIRATION]; ok { 565 output.Expiration = ret[0] 566 } 567 if ret, ok := output.ResponseHeaders[HEADER_RESTORE]; ok { 568 output.Restore = ret[0] 569 } 570 if ret, ok := output.ResponseHeaders[HEADER_OBJECT_TYPE]; ok { 571 output.ObjectType = ret[0] 572 } 573 if ret, ok := output.ResponseHeaders[HEADER_NEXT_APPEND_POSITION]; ok { 574 output.NextAppendPosition = ret[0] 575 } 576 } 577 578 func ParseGetObjectMetadataOutput(output *GetObjectMetadataOutput) { 579 output.AllowOrigin, output.AllowHeader, output.AllowMethod, output.ExposeHeader, output.MaxAgeSeconds = parseCorsHeader(output.BaseModel) 580 parseUnCommonHeader(output) 581 if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok { 582 output.StorageClass = ParseStringToStorageClassType(ret[0]) 583 } 584 if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok { 585 output.ETag = ret[0] 586 } 587 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_TYPE]; ok { 588 output.ContentType = ret[0] 589 } 590 591 output.SseHeader = parseSseHeader(output.ResponseHeaders) 592 if ret, ok := output.ResponseHeaders[HEADER_LASTMODIFIED]; ok { 593 ret, err := time.Parse(time.RFC1123, ret[0]) 594 if err == nil { 595 output.LastModified = ret 596 } 597 } 598 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LENGTH]; ok { 599 output.ContentLength = StringToInt64(ret[0], 0) 600 } 601 602 output.Metadata = make(map[string]string) 603 604 for key, value := range output.ResponseHeaders { 605 if strings.HasPrefix(key, PREFIX_META) { 606 _key := key[len(PREFIX_META):] 607 output.ResponseHeaders[_key] = value 608 output.Metadata[_key] = value[0] 609 delete(output.ResponseHeaders, key) 610 } 611 } 612 613 } 614 615 func ParseCopyObjectOutput(output *CopyObjectOutput) { 616 if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok { 617 output.VersionId = ret[0] 618 } 619 output.SseHeader = parseSseHeader(output.ResponseHeaders) 620 if ret, ok := output.ResponseHeaders[HEADER_COPY_SOURCE_VERSION_ID]; ok { 621 output.CopySourceVersionId = ret[0] 622 } 623 } 624 625 func ParsePutObjectOutput(output *PutObjectOutput) { 626 if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok { 627 output.VersionId = ret[0] 628 } 629 output.SseHeader = parseSseHeader(output.ResponseHeaders) 630 if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok { 631 output.StorageClass = ParseStringToStorageClassType(ret[0]) 632 } 633 if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok { 634 output.ETag = ret[0] 635 } 636 } 637 638 func ParseInitiateMultipartUploadOutput(output *InitiateMultipartUploadOutput) { 639 output.SseHeader = parseSseHeader(output.ResponseHeaders) 640 } 641 642 func ParseUploadPartOutput(output *UploadPartOutput) { 643 output.SseHeader = parseSseHeader(output.ResponseHeaders) 644 if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok { 645 output.ETag = ret[0] 646 } 647 } 648 649 func ParseCompleteMultipartUploadOutput(output *CompleteMultipartUploadOutput) { 650 output.SseHeader = parseSseHeader(output.ResponseHeaders) 651 if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok { 652 output.VersionId = ret[0] 653 } 654 } 655 656 func ParseCopyPartOutput(output *CopyPartOutput) { 657 output.SseHeader = parseSseHeader(output.ResponseHeaders) 658 } 659 660 func ParseGetBucketMetadataOutput(output *GetBucketMetadataOutput) { 661 output.AllowOrigin, output.AllowHeader, output.AllowMethod, output.ExposeHeader, output.MaxAgeSeconds = parseCorsHeader(output.BaseModel) 662 if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS]; ok { 663 output.StorageClass = ParseStringToStorageClassType(ret[0]) 664 } else if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok { 665 output.StorageClass = ParseStringToStorageClassType(ret[0]) 666 } 667 if ret, ok := output.ResponseHeaders[HEADER_VERSION_OBS]; ok { 668 output.Version = ret[0] 669 } 670 if ret, ok := output.ResponseHeaders[HEADER_BUCKET_REGION]; ok { 671 output.Location = ret[0] 672 } else if ret, ok := output.ResponseHeaders[HEADER_BUCKET_LOCATION_OBS]; ok { 673 output.Location = ret[0] 674 } 675 if ret, ok := output.ResponseHeaders[HEADER_EPID_HEADERS]; ok { 676 output.Epid = ret[0] 677 } 678 } 679 680 func parseContentHeader(output *SetObjectMetadataOutput) { 681 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_DISPOSITION]; ok { 682 output.ContentDisposition = ret[0] 683 } 684 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_ENCODING]; ok { 685 output.ContentEncoding = ret[0] 686 } 687 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LANGUAGE]; ok { 688 output.ContentLanguage = ret[0] 689 } 690 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_TYPE]; ok { 691 output.ContentType = ret[0] 692 } 693 } 694 695 func ParseSetObjectMetadataOutput(output *SetObjectMetadataOutput) { 696 if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS]; ok { 697 output.StorageClass = ParseStringToStorageClassType(ret[0]) 698 } else if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok { 699 output.StorageClass = ParseStringToStorageClassType(ret[0]) 700 } 701 if ret, ok := output.ResponseHeaders[HEADER_METADATA_DIRECTIVE]; ok { 702 output.MetadataDirective = MetadataDirectiveType(ret[0]) 703 } 704 if ret, ok := output.ResponseHeaders[HEADER_CACHE_CONTROL]; ok { 705 output.CacheControl = ret[0] 706 } 707 parseContentHeader(output) 708 if ret, ok := output.ResponseHeaders[HEADER_EXPIRES]; ok { 709 output.Expires = ret[0] 710 } 711 if ret, ok := output.ResponseHeaders[HEADER_WEBSITE_REDIRECT_LOCATION]; ok { 712 output.WebsiteRedirectLocation = ret[0] 713 } 714 output.Metadata = make(map[string]string) 715 716 for key, value := range output.ResponseHeaders { 717 if strings.HasPrefix(key, PREFIX_META) { 718 _key := key[len(PREFIX_META):] 719 output.ResponseHeaders[_key] = value 720 output.Metadata[_key] = value[0] 721 delete(output.ResponseHeaders, key) 722 } 723 } 724 } 725 func ParseDeleteObjectOutput(output *DeleteObjectOutput) { 726 if versionId, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok { 727 output.VersionId = versionId[0] 728 } 729 730 if deleteMarker, ok := output.ResponseHeaders[HEADER_DELETE_MARKER]; ok { 731 output.DeleteMarker = deleteMarker[0] == "true" 732 } 733 } 734 735 func ParseGetObjectOutput(output *GetObjectOutput) { 736 ParseGetObjectMetadataOutput(&output.GetObjectMetadataOutput) 737 if ret, ok := output.ResponseHeaders[HEADER_DELETE_MARKER]; ok { 738 output.DeleteMarker = ret[0] == "true" 739 } 740 if ret, ok := output.ResponseHeaders[HEADER_CACHE_CONTROL]; ok { 741 output.CacheControl = ret[0] 742 } 743 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_DISPOSITION]; ok { 744 output.ContentDisposition = ret[0] 745 } 746 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_ENCODING]; ok { 747 output.ContentEncoding = ret[0] 748 } 749 if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LANGUAGE]; ok { 750 output.ContentLanguage = ret[0] 751 } 752 if ret, ok := output.ResponseHeaders[HEADER_EXPIRES]; ok { 753 output.Expires = ret[0] 754 } 755 } 756 757 func ConvertRequestToIoReaderV2(req interface{}) (io.Reader, string, error) { 758 data, err := TransToXml(req) 759 if err == nil { 760 if isDebugLogEnabled() { 761 doLog(LEVEL_DEBUG, "Do http request with data: %s", string(data)) 762 } 763 return bytes.NewReader(data), Base64Md5(data), nil 764 } 765 return nil, "", err 766 } 767 768 func ConvertRequestToIoReader(req interface{}) (io.Reader, error) { 769 body, err := TransToXml(req) 770 if err == nil { 771 if isDebugLogEnabled() { 772 doLog(LEVEL_DEBUG, "Do http request with data: %s", string(body)) 773 } 774 return bytes.NewReader(body), nil 775 } 776 return nil, err 777 } 778 779 func ParseResponseToBaseModel(resp *http.Response, baseModel IBaseModel, xmlResult bool, isObs bool) (err error) { 780 readCloser, ok := baseModel.(IReadCloser) 781 if !ok { 782 defer func() { 783 errMsg := resp.Body.Close() 784 if errMsg != nil { 785 doLog(LEVEL_WARN, "Failed to close response with reason: %v", errMsg) 786 } 787 }() 788 body, err := ioutil.ReadAll(resp.Body) 789 if err == nil && len(body) > 0 { 790 if xmlResult { 791 err = ParseXml(body, baseModel) 792 if err != nil { 793 doLog(LEVEL_ERROR, "Unmarshal error: %v", err) 794 } 795 } else { 796 s := reflect.TypeOf(baseModel).Elem() 797 for i := 0; i < s.NumField(); i++ { 798 if s.Field(i).Tag == "json:\"body\"" { 799 reflect.ValueOf(baseModel).Elem().FieldByName(s.Field(i).Name).SetString(string(body)) 800 break 801 } 802 } 803 } 804 } 805 } else { 806 readCloser.setReadCloser(resp.Body) 807 } 808 809 baseModel.setStatusCode(resp.StatusCode) 810 responseHeaders := cleanHeaderPrefix(resp.Header) 811 baseModel.setResponseHeaders(responseHeaders) 812 if values, ok := responseHeaders[HEADER_REQUEST_ID]; ok { 813 baseModel.setRequestId(values[0]) 814 } 815 return 816 } 817 818 func ParseResponseToObsError(resp *http.Response, isObs bool) error { 819 obsError := ObsError{} 820 respError := ParseResponseToBaseModel(resp, &obsError, true, isObs) 821 if respError != nil { 822 doLog(LEVEL_WARN, "Parse response to BaseModel with error: %v", respError) 823 } 824 obsError.Status = resp.Status 825 return obsError 826 }