|
- // Copyright 2019 Huawei Technologies Co.,Ltd.
- // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- // this file except in compliance with the License. You may obtain a copy of the
- // License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software distributed
- // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- // CONDITIONS OF ANY KIND, either express or implied. See the License for the
- // specific language governing permissions and limitations under the License.
-
- //nolint:golint, unused
- package obs
-
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "reflect"
- "strings"
- "time"
- )
-
- func cleanHeaderPrefix(header http.Header) map[string][]string {
- responseHeaders := make(map[string][]string)
- for key, value := range header {
- if len(value) > 0 {
- key = strings.ToLower(key)
- if strings.HasPrefix(key, HEADER_PREFIX) || strings.HasPrefix(key, HEADER_PREFIX_OBS) {
- key = key[len(HEADER_PREFIX):]
- }
- responseHeaders[key] = value
- }
- }
- return responseHeaders
- }
-
- // ParseStringToEventType converts string value to EventType value and returns it
- func ParseStringToEventType(value string) (ret EventType) {
- switch value {
- case "ObjectCreated:*", "s3:ObjectCreated:*":
- ret = ObjectCreatedAll
- case "ObjectCreated:Put", "s3:ObjectCreated:Put":
- ret = ObjectCreatedPut
- case "ObjectCreated:Post", "s3:ObjectCreated:Post":
- ret = ObjectCreatedPost
- case "ObjectCreated:Copy", "s3:ObjectCreated:Copy":
- ret = ObjectCreatedCopy
- case "ObjectCreated:CompleteMultipartUpload", "s3:ObjectCreated:CompleteMultipartUpload":
- ret = ObjectCreatedCompleteMultipartUpload
- case "ObjectRemoved:*", "s3:ObjectRemoved:*":
- ret = ObjectRemovedAll
- case "ObjectRemoved:Delete", "s3:ObjectRemoved:Delete":
- ret = ObjectRemovedDelete
- case "ObjectRemoved:DeleteMarkerCreated", "s3:ObjectRemoved:DeleteMarkerCreated":
- ret = ObjectRemovedDeleteMarkerCreated
- default:
- ret = ""
- }
- return
- }
-
- // ParseStringToStorageClassType converts string value to StorageClassType value and returns it
- func ParseStringToStorageClassType(value string) (ret StorageClassType) {
- switch value {
- case "STANDARD":
- ret = StorageClassStandard
- case "STANDARD_IA", "WARM":
- ret = StorageClassWarm
- case "GLACIER", "COLD":
- ret = StorageClassCold
- default:
- ret = ""
- }
- return
- }
-
- func prepareGrantURI(grant Grant) string {
- if grant.Grantee.URI == GroupAllUsers || grant.Grantee.URI == GroupAuthenticatedUsers {
- return fmt.Sprintf("<URI>%s%s</URI>", "http://acs.amazonaws.com/groups/global/", grant.Grantee.URI)
- }
- if grant.Grantee.URI == GroupLogDelivery {
- return fmt.Sprintf("<URI>%s%s</URI>", "http://acs.amazonaws.com/groups/s3/", grant.Grantee.URI)
- }
- return fmt.Sprintf("<URI>%s</URI>", grant.Grantee.URI)
- }
-
- func convertGrantToXML(grant Grant, isObs bool, isBucket bool) string {
- xml := make([]string, 0, 4)
-
- if grant.Grantee.Type == GranteeUser {
- if isObs {
- xml = append(xml, "<Grant><Grantee>")
- } else {
- xml = append(xml, fmt.Sprintf("<Grant><Grantee xsi:type=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", grant.Grantee.Type))
- }
- if grant.Grantee.ID != "" {
- granteeID := XmlTranscoding(grant.Grantee.ID)
- xml = append(xml, fmt.Sprintf("<ID>%s</ID>", granteeID))
- }
- if !isObs && grant.Grantee.DisplayName != "" {
- granteeDisplayName := XmlTranscoding(grant.Grantee.DisplayName)
- xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", granteeDisplayName))
- }
- xml = append(xml, "</Grantee>")
- } else {
- if !isObs {
- xml = append(xml, fmt.Sprintf("<Grant><Grantee xsi:type=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", grant.Grantee.Type))
- xml = append(xml, prepareGrantURI(grant))
- xml = append(xml, "</Grantee>")
- } else if grant.Grantee.URI == GroupAllUsers {
- xml = append(xml, "<Grant><Grantee>")
- xml = append(xml, fmt.Sprintf("<Canned>Everyone</Canned>"))
- xml = append(xml, "</Grantee>")
- } else {
- return strings.Join(xml, "")
- }
- }
-
- xml = append(xml, fmt.Sprintf("<Permission>%s</Permission>", grant.Permission))
- if isObs && isBucket {
- xml = append(xml, fmt.Sprintf("<Delivered>%t</Delivered>", grant.Delivered))
- }
- xml = append(xml, fmt.Sprintf("</Grant>"))
- return strings.Join(xml, "")
- }
-
- func hasLoggingTarget(input BucketLoggingStatus) bool {
- if input.TargetBucket != "" || input.TargetPrefix != "" || len(input.TargetGrants) > 0 {
- return true
- }
- return false
- }
-
- // ConvertLoggingStatusToXml converts BucketLoggingStatus value to XML data and returns it
- func ConvertLoggingStatusToXml(input BucketLoggingStatus, returnMd5 bool, isObs bool) (data string, md5 string) {
- grantsLength := len(input.TargetGrants)
- xml := make([]string, 0, 8+grantsLength)
-
- xml = append(xml, "<BucketLoggingStatus>")
- if isObs && input.Agency != "" {
- agency := XmlTranscoding(input.Agency)
- xml = append(xml, fmt.Sprintf("<Agency>%s</Agency>", agency))
- }
- if hasLoggingTarget(input) {
- xml = append(xml, "<LoggingEnabled>")
- if input.TargetBucket != "" {
- xml = append(xml, fmt.Sprintf("<TargetBucket>%s</TargetBucket>", input.TargetBucket))
- }
- if input.TargetPrefix != "" {
- targetPrefix := XmlTranscoding(input.TargetPrefix)
- xml = append(xml, fmt.Sprintf("<TargetPrefix>%s</TargetPrefix>", targetPrefix))
- }
- if grantsLength > 0 {
- xml = append(xml, "<TargetGrants>")
- for _, grant := range input.TargetGrants {
- xml = append(xml, convertGrantToXML(grant, isObs, false))
- }
- xml = append(xml, "</TargetGrants>")
- }
-
- xml = append(xml, "</LoggingEnabled>")
- }
- xml = append(xml, "</BucketLoggingStatus>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- // ConvertAclToXml converts AccessControlPolicy value to XML data and returns it
- func ConvertAclToXml(input AccessControlPolicy, returnMd5 bool, isObs bool) (data string, md5 string) {
- xml := make([]string, 0, 4+len(input.Grants))
- ownerID := XmlTranscoding(input.Owner.ID)
- xml = append(xml, fmt.Sprintf("<AccessControlPolicy><Owner><ID>%s</ID>", ownerID))
- if !isObs && input.Owner.DisplayName != "" {
- ownerDisplayName := XmlTranscoding(input.Owner.DisplayName)
- xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", ownerDisplayName))
- }
- if isObs && input.Delivered != "" {
- objectDelivered := XmlTranscoding(input.Delivered)
- xml = append(xml, fmt.Sprintf("</Owner><Delivered>%s</Delivered><AccessControlList>", objectDelivered))
- } else {
- xml = append(xml, "</Owner><AccessControlList>")
- }
- for _, grant := range input.Grants {
- xml = append(xml, convertGrantToXML(grant, isObs, false))
- }
- xml = append(xml, "</AccessControlList></AccessControlPolicy>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- func convertBucketACLToXML(input AccessControlPolicy, returnMd5 bool, isObs bool) (data string, md5 string) {
- xml := make([]string, 0, 4+len(input.Grants))
- ownerID := XmlTranscoding(input.Owner.ID)
- xml = append(xml, fmt.Sprintf("<AccessControlPolicy><Owner><ID>%s</ID>", ownerID))
- if !isObs && input.Owner.DisplayName != "" {
- ownerDisplayName := XmlTranscoding(input.Owner.DisplayName)
- xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", ownerDisplayName))
- }
-
- xml = append(xml, "</Owner><AccessControlList>")
-
- for _, grant := range input.Grants {
- xml = append(xml, convertGrantToXML(grant, isObs, true))
- }
- xml = append(xml, "</AccessControlList></AccessControlPolicy>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- func convertConditionToXML(condition Condition) string {
- xml := make([]string, 0, 2)
- if condition.KeyPrefixEquals != "" {
- keyPrefixEquals := XmlTranscoding(condition.KeyPrefixEquals)
- xml = append(xml, fmt.Sprintf("<KeyPrefixEquals>%s</KeyPrefixEquals>", keyPrefixEquals))
- }
- if condition.HttpErrorCodeReturnedEquals != "" {
- xml = append(xml, fmt.Sprintf("<HttpErrorCodeReturnedEquals>%s</HttpErrorCodeReturnedEquals>", condition.HttpErrorCodeReturnedEquals))
- }
- if len(xml) > 0 {
- return fmt.Sprintf("<Condition>%s</Condition>", strings.Join(xml, ""))
- }
- return ""
- }
-
- func prepareRoutingRule(input BucketWebsiteConfiguration) string {
- xml := make([]string, 0, len(input.RoutingRules)*10)
- for _, routingRule := range input.RoutingRules {
- xml = append(xml, "<RoutingRule>")
- xml = append(xml, "<Redirect>")
- if routingRule.Redirect.Protocol != "" {
- xml = append(xml, fmt.Sprintf("<Protocol>%s</Protocol>", routingRule.Redirect.Protocol))
- }
- if routingRule.Redirect.HostName != "" {
- xml = append(xml, fmt.Sprintf("<HostName>%s</HostName>", routingRule.Redirect.HostName))
- }
- if routingRule.Redirect.ReplaceKeyPrefixWith != "" {
- replaceKeyPrefixWith := XmlTranscoding(routingRule.Redirect.ReplaceKeyPrefixWith)
- xml = append(xml, fmt.Sprintf("<ReplaceKeyPrefixWith>%s</ReplaceKeyPrefixWith>", replaceKeyPrefixWith))
- }
-
- if routingRule.Redirect.ReplaceKeyWith != "" {
- replaceKeyWith := XmlTranscoding(routingRule.Redirect.ReplaceKeyWith)
- xml = append(xml, fmt.Sprintf("<ReplaceKeyWith>%s</ReplaceKeyWith>", replaceKeyWith))
- }
- if routingRule.Redirect.HttpRedirectCode != "" {
- xml = append(xml, fmt.Sprintf("<HttpRedirectCode>%s</HttpRedirectCode>", routingRule.Redirect.HttpRedirectCode))
- }
- xml = append(xml, "</Redirect>")
-
- if ret := convertConditionToXML(routingRule.Condition); ret != "" {
- xml = append(xml, ret)
- }
- xml = append(xml, "</RoutingRule>")
- }
- return strings.Join(xml, "")
- }
-
- // ConvertWebsiteConfigurationToXml converts BucketWebsiteConfiguration value to XML data and returns it
- func ConvertWebsiteConfigurationToXml(input BucketWebsiteConfiguration, returnMd5 bool) (data string, md5 string) {
- routingRuleLength := len(input.RoutingRules)
- xml := make([]string, 0, 6+routingRuleLength*10)
- xml = append(xml, "<WebsiteConfiguration>")
-
- if input.RedirectAllRequestsTo.HostName != "" {
- xml = append(xml, fmt.Sprintf("<RedirectAllRequestsTo><HostName>%s</HostName>", input.RedirectAllRequestsTo.HostName))
- if input.RedirectAllRequestsTo.Protocol != "" {
- xml = append(xml, fmt.Sprintf("<Protocol>%s</Protocol>", input.RedirectAllRequestsTo.Protocol))
- }
- xml = append(xml, "</RedirectAllRequestsTo>")
- } else {
- if input.IndexDocument.Suffix != "" {
- indexDocumentSuffix := XmlTranscoding(input.IndexDocument.Suffix)
- xml = append(xml, fmt.Sprintf("<IndexDocument><Suffix>%s</Suffix></IndexDocument>", indexDocumentSuffix))
- }
- if input.ErrorDocument.Key != "" {
- errorDocumentKey := XmlTranscoding(input.ErrorDocument.Key)
- xml = append(xml, fmt.Sprintf("<ErrorDocument><Key>%s</Key></ErrorDocument>", errorDocumentKey))
- }
- if routingRuleLength > 0 {
- xml = append(xml, "<RoutingRules>")
- xml = append(xml, prepareRoutingRule(input))
- xml = append(xml, "</RoutingRules>")
- }
- }
-
- xml = append(xml, "</WebsiteConfiguration>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- func convertTransitionsToXML(transitions []Transition, isObs bool) string {
- if length := len(transitions); length > 0 {
- xml := make([]string, 0, length)
- for _, transition := range transitions {
- var temp string
- if transition.Days > 0 {
- temp = fmt.Sprintf("<Days>%d</Days>", transition.Days)
- } else if !transition.Date.IsZero() {
- temp = fmt.Sprintf("<Date>%s</Date>", transition.Date.UTC().Format(ISO8601_MIDNIGHT_DATE_FORMAT))
- }
- if temp != "" {
- if !isObs {
- storageClass := string(transition.StorageClass)
- if transition.StorageClass == StorageClassWarm {
- storageClass = string(storageClassStandardIA)
- } else if transition.StorageClass == StorageClassCold {
- storageClass = string(storageClassGlacier)
- }
- xml = append(xml, fmt.Sprintf("<Transition>%s<StorageClass>%s</StorageClass></Transition>", temp, storageClass))
- } else {
- xml = append(xml, fmt.Sprintf("<Transition>%s<StorageClass>%s</StorageClass></Transition>", temp, transition.StorageClass))
- }
- }
- }
- return strings.Join(xml, "")
- }
- return ""
- }
-
- func convertExpirationToXML(expiration Expiration) string {
- if expiration.Days > 0 {
- return fmt.Sprintf("<Expiration><Days>%d</Days></Expiration>", expiration.Days)
- } else if !expiration.Date.IsZero() {
- return fmt.Sprintf("<Expiration><Date>%s</Date></Expiration>", expiration.Date.UTC().Format(ISO8601_MIDNIGHT_DATE_FORMAT))
- }
- return ""
- }
- func convertNoncurrentVersionTransitionsToXML(noncurrentVersionTransitions []NoncurrentVersionTransition, isObs bool) string {
- if length := len(noncurrentVersionTransitions); length > 0 {
- xml := make([]string, 0, length)
- for _, noncurrentVersionTransition := range noncurrentVersionTransitions {
- if noncurrentVersionTransition.NoncurrentDays > 0 {
- storageClass := string(noncurrentVersionTransition.StorageClass)
- if !isObs {
- if storageClass == string(StorageClassWarm) {
- storageClass = string(storageClassStandardIA)
- } else if storageClass == string(StorageClassCold) {
- storageClass = string(storageClassGlacier)
- }
- }
- xml = append(xml, fmt.Sprintf("<NoncurrentVersionTransition><NoncurrentDays>%d</NoncurrentDays>"+
- "<StorageClass>%s</StorageClass></NoncurrentVersionTransition>",
- noncurrentVersionTransition.NoncurrentDays, storageClass))
- }
- }
- return strings.Join(xml, "")
- }
- return ""
- }
- func convertNoncurrentVersionExpirationToXML(noncurrentVersionExpiration NoncurrentVersionExpiration) string {
- if noncurrentVersionExpiration.NoncurrentDays > 0 {
- return fmt.Sprintf("<NoncurrentVersionExpiration><NoncurrentDays>%d</NoncurrentDays></NoncurrentVersionExpiration>", noncurrentVersionExpiration.NoncurrentDays)
- }
- return ""
- }
-
- // ConvertLifecyleConfigurationToXml converts BucketLifecyleConfiguration value to XML data and returns it
- func ConvertLifecyleConfigurationToXml(input BucketLifecyleConfiguration, returnMd5 bool, isObs bool) (data string, md5 string) {
- xml := make([]string, 0, 2+len(input.LifecycleRules)*9)
- xml = append(xml, "<LifecycleConfiguration>")
- for _, lifecyleRule := range input.LifecycleRules {
- xml = append(xml, "<Rule>")
- if lifecyleRule.ID != "" {
- lifecyleRuleID := XmlTranscoding(lifecyleRule.ID)
- xml = append(xml, fmt.Sprintf("<ID>%s</ID>", lifecyleRuleID))
- }
- lifecyleRulePrefix := XmlTranscoding(lifecyleRule.Prefix)
- xml = append(xml, fmt.Sprintf("<Prefix>%s</Prefix>", lifecyleRulePrefix))
- xml = append(xml, fmt.Sprintf("<Status>%s</Status>", lifecyleRule.Status))
- if ret := convertTransitionsToXML(lifecyleRule.Transitions, isObs); ret != "" {
- xml = append(xml, ret)
- }
- if ret := convertExpirationToXML(lifecyleRule.Expiration); ret != "" {
- xml = append(xml, ret)
- }
- if ret := convertNoncurrentVersionTransitionsToXML(lifecyleRule.NoncurrentVersionTransitions, isObs); ret != "" {
- xml = append(xml, ret)
- }
- if ret := convertNoncurrentVersionExpirationToXML(lifecyleRule.NoncurrentVersionExpiration); ret != "" {
- xml = append(xml, ret)
- }
- xml = append(xml, "</Rule>")
- }
- xml = append(xml, "</LifecycleConfiguration>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- func converntFilterRulesToXML(filterRules []FilterRule, isObs bool) string {
- if length := len(filterRules); length > 0 {
- xml := make([]string, 0, length*4)
- for _, filterRule := range filterRules {
- xml = append(xml, "<FilterRule>")
- if filterRule.Name != "" {
- filterRuleName := XmlTranscoding(filterRule.Name)
- xml = append(xml, fmt.Sprintf("<Name>%s</Name>", filterRuleName))
- }
- if filterRule.Value != "" {
- filterRuleValue := XmlTranscoding(filterRule.Value)
- xml = append(xml, fmt.Sprintf("<Value>%s</Value>", filterRuleValue))
- }
- xml = append(xml, "</FilterRule>")
- }
- if !isObs {
- return fmt.Sprintf("<Filter><S3Key>%s</S3Key></Filter>", strings.Join(xml, ""))
- }
- return fmt.Sprintf("<Filter><Object>%s</Object></Filter>", strings.Join(xml, ""))
- }
- return ""
- }
-
- func converntEventsToXML(events []EventType, isObs bool) string {
- if length := len(events); length > 0 {
- xml := make([]string, 0, length)
- if !isObs {
- for _, event := range events {
- xml = append(xml, fmt.Sprintf("<Event>%s%s</Event>", "s3:", event))
- }
- } else {
- for _, event := range events {
- xml = append(xml, fmt.Sprintf("<Event>%s</Event>", event))
- }
- }
- return strings.Join(xml, "")
- }
- return ""
- }
-
- func converntConfigureToXML(topicConfiguration TopicConfiguration, xmlElem string, isObs bool) string {
- xml := make([]string, 0, 6)
- xml = append(xml, xmlElem)
- if topicConfiguration.ID != "" {
- topicConfigurationID := XmlTranscoding(topicConfiguration.ID)
- xml = append(xml, fmt.Sprintf("<Id>%s</Id>", topicConfigurationID))
- }
- topicConfigurationTopic := XmlTranscoding(topicConfiguration.Topic)
- xml = append(xml, fmt.Sprintf("<Topic>%s</Topic>", topicConfigurationTopic))
-
- if ret := converntEventsToXML(topicConfiguration.Events, isObs); ret != "" {
- xml = append(xml, ret)
- }
- if ret := converntFilterRulesToXML(topicConfiguration.FilterRules, isObs); ret != "" {
- xml = append(xml, ret)
- }
- tempElem := xmlElem[0:1] + "/" + xmlElem[1:]
- xml = append(xml, tempElem)
- return strings.Join(xml, "")
- }
-
- // ConverntObsRestoreToXml converts RestoreObjectInput value to XML data and returns it
- func ConverntObsRestoreToXml(restoreObjectInput RestoreObjectInput) string {
- xml := make([]string, 0, 2)
- xml = append(xml, fmt.Sprintf("<RestoreRequest><Days>%d</Days>", restoreObjectInput.Days))
- if restoreObjectInput.Tier != "Bulk" {
- xml = append(xml, fmt.Sprintf("<RestoreJob><Tier>%s</Tier></RestoreJob>", restoreObjectInput.Tier))
- }
- xml = append(xml, fmt.Sprintf("</RestoreRequest>"))
- data := strings.Join(xml, "")
- return data
- }
-
- // ConvertNotificationToXml converts BucketNotification value to XML data and returns it
- func ConvertNotificationToXml(input BucketNotification, returnMd5 bool, isObs bool) (data string, md5 string) {
- xml := make([]string, 0, 2+len(input.TopicConfigurations)*6)
- xml = append(xml, "<NotificationConfiguration>")
- for _, topicConfiguration := range input.TopicConfigurations {
- ret := converntConfigureToXML(topicConfiguration, "<TopicConfiguration>", isObs)
- xml = append(xml, ret)
- }
- xml = append(xml, "</NotificationConfiguration>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- // ConvertCompleteMultipartUploadInputToXml converts CompleteMultipartUploadInput value to XML data and returns it
- func ConvertCompleteMultipartUploadInputToXml(input CompleteMultipartUploadInput, returnMd5 bool) (data string, md5 string) {
- xml := make([]string, 0, 2+len(input.Parts)*4)
- xml = append(xml, "<CompleteMultipartUpload>")
- for _, part := range input.Parts {
- xml = append(xml, "<Part>")
- xml = append(xml, fmt.Sprintf("<PartNumber>%d</PartNumber>", part.PartNumber))
- xml = append(xml, fmt.Sprintf("<ETag>%s</ETag>", part.ETag))
- xml = append(xml, "</Part>")
- }
- xml = append(xml, "</CompleteMultipartUpload>")
- data = strings.Join(xml, "")
- if returnMd5 {
- md5 = Base64Md5([]byte(data))
- }
- return
- }
-
- func parseSseHeader(responseHeaders map[string][]string) (sseHeader ISseHeader) {
- if ret, ok := responseHeaders[HEADER_SSEC_ENCRYPTION]; ok {
- sseCHeader := SseCHeader{Encryption: ret[0]}
- if ret, ok = responseHeaders[HEADER_SSEC_KEY_MD5]; ok {
- sseCHeader.KeyMD5 = ret[0]
- }
- sseHeader = sseCHeader
- } else if ret, ok := responseHeaders[HEADER_SSEKMS_ENCRYPTION]; ok {
- sseKmsHeader := SseKmsHeader{Encryption: ret[0]}
- if ret, ok = responseHeaders[HEADER_SSEKMS_KEY]; ok {
- sseKmsHeader.Key = ret[0]
- } else if ret, ok = responseHeaders[HEADER_SSEKMS_ENCRYPT_KEY_OBS]; ok {
- sseKmsHeader.Key = ret[0]
- }
- sseHeader = sseKmsHeader
- }
- return
- }
-
- func parseCorsHeader(output BaseModel) (AllowOrigin, AllowHeader, AllowMethod, ExposeHeader string, MaxAgeSeconds int) {
- if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_ORIGIN]; ok {
- AllowOrigin = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_HEADERS]; ok {
- AllowHeader = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_MAX_AGE]; ok {
- MaxAgeSeconds = StringToInt(ret[0], 0)
- }
- if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_METHODS]; ok {
- AllowMethod = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_EXPOSE_HEADERS]; ok {
- ExposeHeader = ret[0]
- }
- return
- }
-
- func parseUnCommonHeader(output *GetObjectMetadataOutput) {
- if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
- output.VersionId = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_WEBSITE_REDIRECT_LOCATION]; ok {
- output.WebsiteRedirectLocation = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_EXPIRATION]; ok {
- output.Expiration = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_RESTORE]; ok {
- output.Restore = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_OBJECT_TYPE]; ok {
- output.ObjectType = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_NEXT_APPEND_POSITION]; ok {
- output.NextAppendPosition = ret[0]
- }
- }
-
- // ParseGetObjectMetadataOutput sets GetObjectMetadataOutput field values with response headers
- func ParseGetObjectMetadataOutput(output *GetObjectMetadataOutput) {
- output.AllowOrigin, output.AllowHeader, output.AllowMethod, output.ExposeHeader, output.MaxAgeSeconds = parseCorsHeader(output.BaseModel)
- parseUnCommonHeader(output)
- if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
- output.StorageClass = ParseStringToStorageClassType(ret[0])
- }
- if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok {
- output.ETag = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_TYPE]; ok {
- output.ContentType = ret[0]
- }
-
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- if ret, ok := output.ResponseHeaders[HEADER_LASTMODIFIED]; ok {
- ret, err := time.Parse(time.RFC1123, ret[0])
- if err == nil {
- output.LastModified = ret
- }
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LENGTH]; ok {
- output.ContentLength = StringToInt64(ret[0], 0)
- }
-
- output.Metadata = make(map[string]string)
-
- for key, value := range output.ResponseHeaders {
- if strings.HasPrefix(key, PREFIX_META) {
- _key := key[len(PREFIX_META):]
- output.ResponseHeaders[_key] = value
- output.Metadata[_key] = value[0]
- delete(output.ResponseHeaders, key)
- }
- }
-
- }
-
- // ParseCopyObjectOutput sets CopyObjectOutput field values with response headers
- func ParseCopyObjectOutput(output *CopyObjectOutput) {
- if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
- output.VersionId = ret[0]
- }
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- if ret, ok := output.ResponseHeaders[HEADER_COPY_SOURCE_VERSION_ID]; ok {
- output.CopySourceVersionId = ret[0]
- }
- }
-
- // ParsePutObjectOutput sets PutObjectOutput field values with response headers
- func ParsePutObjectOutput(output *PutObjectOutput) {
- if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
- output.VersionId = ret[0]
- }
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
- output.StorageClass = ParseStringToStorageClassType(ret[0])
- }
- if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok {
- output.ETag = ret[0]
- }
- }
-
- // ParseInitiateMultipartUploadOutput sets InitiateMultipartUploadOutput field values with response headers
- func ParseInitiateMultipartUploadOutput(output *InitiateMultipartUploadOutput) {
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- }
-
- // ParseUploadPartOutput sets UploadPartOutput field values with response headers
- func ParseUploadPartOutput(output *UploadPartOutput) {
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok {
- output.ETag = ret[0]
- }
- }
-
- // ParseCompleteMultipartUploadOutput sets CompleteMultipartUploadOutput field values with response headers
- func ParseCompleteMultipartUploadOutput(output *CompleteMultipartUploadOutput) {
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
- output.VersionId = ret[0]
- }
- }
-
- // ParseCopyPartOutput sets CopyPartOutput field values with response headers
- func ParseCopyPartOutput(output *CopyPartOutput) {
- output.SseHeader = parseSseHeader(output.ResponseHeaders)
- }
-
- // ParseGetBucketMetadataOutput sets GetBucketMetadataOutput field values with response headers
- func ParseGetBucketMetadataOutput(output *GetBucketMetadataOutput) {
- output.AllowOrigin, output.AllowHeader, output.AllowMethod, output.ExposeHeader, output.MaxAgeSeconds = parseCorsHeader(output.BaseModel)
- if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS]; ok {
- output.StorageClass = ParseStringToStorageClassType(ret[0])
- } else if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
- output.StorageClass = ParseStringToStorageClassType(ret[0])
- }
- if ret, ok := output.ResponseHeaders[HEADER_VERSION_OBS]; ok {
- output.Version = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_BUCKET_REGION]; ok {
- output.Location = ret[0]
- } else if ret, ok := output.ResponseHeaders[HEADER_BUCKET_LOCATION_OBS]; ok {
- output.Location = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_EPID_HEADERS]; ok {
- output.Epid = ret[0]
- }
- }
-
- func parseContentHeader(output *SetObjectMetadataOutput) {
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_DISPOSITION]; ok {
- output.ContentDisposition = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_ENCODING]; ok {
- output.ContentEncoding = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LANGUAGE]; ok {
- output.ContentLanguage = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_TYPE]; ok {
- output.ContentType = ret[0]
- }
- }
-
- // ParseSetObjectMetadataOutput sets SetObjectMetadataOutput field values with response headers
- func ParseSetObjectMetadataOutput(output *SetObjectMetadataOutput) {
- if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS]; ok {
- output.StorageClass = ParseStringToStorageClassType(ret[0])
- } else if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
- output.StorageClass = ParseStringToStorageClassType(ret[0])
- }
- if ret, ok := output.ResponseHeaders[HEADER_METADATA_DIRECTIVE]; ok {
- output.MetadataDirective = MetadataDirectiveType(ret[0])
- }
- if ret, ok := output.ResponseHeaders[HEADER_CACHE_CONTROL]; ok {
- output.CacheControl = ret[0]
- }
- parseContentHeader(output)
- if ret, ok := output.ResponseHeaders[HEADER_EXPIRES]; ok {
- output.Expires = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_WEBSITE_REDIRECT_LOCATION]; ok {
- output.WebsiteRedirectLocation = ret[0]
- }
- output.Metadata = make(map[string]string)
-
- for key, value := range output.ResponseHeaders {
- if strings.HasPrefix(key, PREFIX_META) {
- _key := key[len(PREFIX_META):]
- output.ResponseHeaders[_key] = value
- output.Metadata[_key] = value[0]
- delete(output.ResponseHeaders, key)
- }
- }
- }
-
- // ParseDeleteObjectOutput sets DeleteObjectOutput field values with response headers
- func ParseDeleteObjectOutput(output *DeleteObjectOutput) {
- if versionID, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
- output.VersionId = versionID[0]
- }
-
- if deleteMarker, ok := output.ResponseHeaders[HEADER_DELETE_MARKER]; ok {
- output.DeleteMarker = deleteMarker[0] == "true"
- }
- }
-
- // ParseGetObjectOutput sets GetObjectOutput field values with response headers
- func ParseGetObjectOutput(output *GetObjectOutput) {
- ParseGetObjectMetadataOutput(&output.GetObjectMetadataOutput)
- if ret, ok := output.ResponseHeaders[HEADER_DELETE_MARKER]; ok {
- output.DeleteMarker = ret[0] == "true"
- }
- if ret, ok := output.ResponseHeaders[HEADER_CACHE_CONTROL]; ok {
- output.CacheControl = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_DISPOSITION]; ok {
- output.ContentDisposition = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_ENCODING]; ok {
- output.ContentEncoding = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LANGUAGE]; ok {
- output.ContentLanguage = ret[0]
- }
- if ret, ok := output.ResponseHeaders[HEADER_EXPIRES]; ok {
- output.Expires = ret[0]
- }
- }
-
- // ConvertRequestToIoReaderV2 converts req to XML data
- func ConvertRequestToIoReaderV2(req interface{}) (io.Reader, string, error) {
- data, err := TransToXml(req)
- if err == nil {
- if isDebugLogEnabled() {
- doLog(LEVEL_DEBUG, "Do http request with data: %s", string(data))
- }
- return bytes.NewReader(data), Base64Md5(data), nil
- }
- return nil, "", err
- }
-
- // ConvertRequestToIoReader converts req to XML data
- func ConvertRequestToIoReader(req interface{}) (io.Reader, error) {
- body, err := TransToXml(req)
- if err == nil {
- if isDebugLogEnabled() {
- doLog(LEVEL_DEBUG, "Do http request with data: %s", string(body))
- }
- return bytes.NewReader(body), nil
- }
- return nil, err
- }
-
- // ParseResponseToBaseModel gets response from OBS
- func ParseResponseToBaseModel(resp *http.Response, baseModel IBaseModel, xmlResult bool, isObs bool) (err error) {
- readCloser, ok := baseModel.(IReadCloser)
- if !ok {
- defer func() {
- errMsg := resp.Body.Close()
- if errMsg != nil {
- doLog(LEVEL_WARN, "Failed to close response body")
- }
- }()
- body, err := ioutil.ReadAll(resp.Body)
- if err == nil && len(body) > 0 {
- if xmlResult {
- err = ParseXml(body, baseModel)
- } else {
- s := reflect.TypeOf(baseModel).Elem()
- if reflect.TypeOf(baseModel).Elem().Name() == "GetBucketPolicyOutput" {
- for i := 0; i < s.NumField(); i++ {
- if s.Field(i).Tag == "json:\"body\"" {
- reflect.ValueOf(baseModel).Elem().FieldByName(s.Field(i).Name).SetString(string(body))
- break
- }
- }
- } else {
- err = parseJSON(body, baseModel)
- }
- }
- if err != nil {
- doLog(LEVEL_ERROR, "Unmarshal error: %v", err)
- }
- }
- } else {
- readCloser.setReadCloser(resp.Body)
- }
-
- baseModel.setStatusCode(resp.StatusCode)
- responseHeaders := cleanHeaderPrefix(resp.Header)
- baseModel.setResponseHeaders(responseHeaders)
- if values, ok := responseHeaders[HEADER_REQUEST_ID]; ok {
- baseModel.setRequestID(values[0])
- }
- return
- }
-
- // ParseResponseToObsError gets obsError from OBS
- func ParseResponseToObsError(resp *http.Response, isObs bool) error {
- isJson := false
- if contentType, ok := resp.Header[HEADER_CONTENT_TYPE_CAML]; ok {
- jsonType, _ := mimeTypes["json"]
- isJson = contentType[0] == jsonType
- }
- obsError := ObsError{}
- respError := ParseResponseToBaseModel(resp, &obsError, !isJson, isObs)
- if respError != nil {
- doLog(LEVEL_WARN, "Parse response to BaseModel with error: %v", respError)
- }
- obsError.Status = resp.Status
- return obsError
- }
-
- // convertFetchPolicyToJSON converts SetBucketFetchPolicyInput into json format
- func convertFetchPolicyToJSON(input SetBucketFetchPolicyInput) (data string, err error) {
- fetch := map[string]SetBucketFetchPolicyInput{"fetch": input}
- json, err := json.Marshal(fetch)
- if err != nil {
- return "", err
- }
- data = string(json)
- return
- }
-
- // convertFetchJobToJSON converts SetBucketFetchJobInput into json format
- func convertFetchJobToJSON(input SetBucketFetchJobInput) (data string, err error) {
- objectHeaders := make(map[string]string)
- for key, value := range input.ObjectHeaders {
- if value != "" {
- _key := strings.ToLower(key)
- if !strings.HasPrefix(key, HEADER_PREFIX_OBS) {
- _key = HEADER_PREFIX_META_OBS + _key
- }
- objectHeaders[_key] = value
- }
- }
- input.ObjectHeaders = objectHeaders
- json, err := json.Marshal(input)
- if err != nil {
- return "", err
- }
- data = string(json)
- return
- }
|