github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/obs/trait.go (about)

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