github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/openstack/obs/trait.go (about)

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