lib/aws/generated/s3.ex

# WARNING: DO NOT EDIT, AUTO-GENERATED CODE!
# See https://github.com/aws-beam/aws-codegen for more details.

defmodule AWS.S3 do
  alias AWS.Client
  alias AWS.Request

  def metadata do
    %{
      abbreviation: nil,
      api_version: "2006-03-01",
      content_type: "text/xml",
      credential_scope: nil,
      endpoint_prefix: "s3",
      global?: false,
      protocol: "rest-xml",
      service_id: "S3",
      signature_version: "s3",
      signing_name: "s3",
      target_prefix: nil
    }
  end

  @doc """
  This action aborts a multipart upload.

  After a multipart upload is aborted, no additional parts can be uploaded using
  that upload ID. The storage consumed by any previously uploaded parts will be
  freed. However, if any part uploads are currently in progress, those part
  uploads might or might not succeed. As a result, it might be necessary to abort
  a given multipart upload multiple times in order to completely free all storage
  consumed by all parts.

  To verify that all parts have been removed, so you don't get charged for the
  part storage, you should call the
  [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html) action and ensure that the parts list is empty.

  For information about permissions required to use the multipart upload, see
  [Multipart Upload and
  Permissions](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html).

  The following operations are related to `AbortMultipartUpload`:

    *
  [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)     *
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)

    *
  [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)     *
  [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)

    *
  [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)
  """
  def abort_multipart_upload(%Client{} = client, bucket, key, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"},
        {"RequestPayer", "x-amz-request-payer"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"UploadId", "uploadId"}
      ]
      |> Request.build_params(input)

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [{"x-amz-request-charged", "RequestCharged"}]
      )

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Completes a multipart upload by assembling previously uploaded parts.

  You first initiate the multipart upload and then upload all parts using the
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) operation. After successfully uploading all relevant parts of an upload, you
  call this action to complete the upload. Upon receiving this request, Amazon S3
  concatenates all the parts in ascending order by part number to create a new
  object. In the Complete Multipart Upload request, you must provide the parts
  list. You must ensure that the parts list is complete. This action concatenates
  the parts that you provide in the list. For each part in the list, you must
  provide the part number and the `ETag` value, returned after that part was
  uploaded.

  Processing of a Complete Multipart Upload request could take several minutes to
  complete. After Amazon S3 begins processing the request, it sends an HTTP
  response header that specifies a 200 OK response. While processing is in
  progress, Amazon S3 periodically sends white space characters to keep the
  connection from timing out. Because a request could fail after the initial 200
  OK response has been sent, it is important that you check the response body to
  determine whether the request succeeded.

  Note that if `CompleteMultipartUpload` fails, applications should be prepared to
  retry the failed requests. For more information, see [Amazon S3 Error Best
  Practices](https://docs.aws.amazon.com/AmazonS3/latest/dev/ErrorBestPractices.html).

  You cannot use `Content-Type: application/x-www-form-urlencoded` with Complete
  Multipart Upload requests. Also, if you do not provide a `Content-Type` header,
  `CompleteMultipartUpload` returns a 200 OK response.

  For more information about multipart uploads, see [Uploading Objects Using Multipart
  Upload](https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html).

  For information about permissions required to use the multipart upload API, see
  [Multipart Upload and Permissions](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html).

  `CompleteMultipartUpload` has the following special errors:

    * Error code: `EntityTooSmall`

      * Description: Your proposed upload is smaller than the
  minimum allowed object size. Each part must be at least 5 MB in size, except the
  last part.

      * 400 Bad Request

    * Error code: `InvalidPart`

      * Description: One or more of the specified parts could
  not be found. The part might not have been uploaded, or the specified entity tag
  might not have matched the part's entity tag.

      * 400 Bad Request

    * Error code: `InvalidPartOrder`

      * Description: The list of parts was not in ascending
  order. The parts list must be specified in order by part number.

      * 400 Bad Request

    * Error code: `NoSuchUpload`

      * Description: The specified multipart upload does not
  exist. The upload ID might be invalid, or the multipart upload might have been
  aborted or completed.

      * 404 Not Found

  The following operations are related to `CompleteMultipartUpload`:

    *
  [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)     *
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)

    *
  [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)     *
  [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)

    *
  [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)
  """
  def complete_multipart_upload(%Client{} = client, bucket, key, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}"

    {headers, input} =
      [
        {"ChecksumCRC32", "x-amz-checksum-crc32"},
        {"ChecksumCRC32C", "x-amz-checksum-crc32c"},
        {"ChecksumSHA1", "x-amz-checksum-sha1"},
        {"ChecksumSHA256", "x-amz-checksum-sha256"},
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"},
        {"RequestPayer", "x-amz-request-payer"},
        {"SSECustomerAlgorithm", "x-amz-server-side-encryption-customer-algorithm"},
        {"SSECustomerKey", "x-amz-server-side-encryption-customer-key"},
        {"SSECustomerKeyMD5", "x-amz-server-side-encryption-customer-key-MD5"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"UploadId", "uploadId"}
      ]
      |> Request.build_params(input)

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [
          {"x-amz-server-side-encryption-bucket-key-enabled", "BucketKeyEnabled"},
          {"x-amz-expiration", "Expiration"},
          {"x-amz-request-charged", "RequestCharged"},
          {"x-amz-server-side-encryption-aws-kms-key-id", "SSEKMSKeyId"},
          {"x-amz-server-side-encryption", "ServerSideEncryption"},
          {"x-amz-version-id", "VersionId"}
        ]
      )

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :post,
      url_path,
      query_params,
      headers,
      input,
      options,
      nil
    )
  end

  @doc """
  Creates a copy of an object that is already stored in Amazon S3.

  You can store individual objects of up to 5 TB in Amazon S3. You create a copy
  of your object up to 5 GB in size in a single atomic action using this API.
  However, to copy an object greater than 5 GB, you must use the multipart upload
  Upload Part - Copy (UploadPartCopy) API. For more information, see [Copy Object Using the REST Multipart Upload
  API](https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjctsUsingRESTMPUapi.html).

  All copy requests must be authenticated. Additionally, you must have *read*
  access to the source object and *write* access to the destination bucket. For
  more information, see [REST Authentication](https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html).
  Both the Region that you want to copy the object from and the Region that you
  want to copy the object to must be enabled for your account.

  A copy request might return an error when Amazon S3 receives the copy request or
  while Amazon S3 is copying the files. If the error occurs before the copy action
  starts, you receive a standard Amazon S3 error. If the error occurs during the
  copy operation, the error response is embedded in the `200 OK` response. This
  means that a `200 OK` response can contain either a success or an error. Design
  your application to parse the contents of the response and handle it
  appropriately.

  If the copy is successful, you receive a response with information about the
  copied object.

  If the request is an HTTP 1.1 request, the response is chunk encoded. If it were
  not, it would not contain the content-length, and you would need to read the
  entire body.

  The copy request charge is based on the storage class and Region that you
  specify for the destination object. For pricing information, see [Amazon S3 pricing](http://aws.amazon.com/s3/pricing/).

  Amazon S3 transfer acceleration does not support cross-Region copies. If you
  request a cross-Region copy using a transfer acceleration endpoint, you get a
  400 `Bad Request` error. For more information, see [Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html).

  ## Metadata

  When copying an object, you can preserve all metadata (default) or specify new
  metadata. However, the ACL is not preserved and is set to private for the user
  making the request. To override the default ACL setting, specify a new ACL when
  generating a copy request. For more information, see [Using ACLs](https://docs.aws.amazon.com/AmazonS3/latest/dev/S3_ACLs_UsingACLs.html).

  To specify whether you want the object metadata copied from the source object or
  replaced with metadata provided in the request, you can optionally add the
  `x-amz-metadata-directive` header. When you grant permissions, you can use the
  `s3:x-amz-metadata-directive` condition key to enforce certain metadata behavior
  when objects are uploaded. For more information, see [Specifying Conditions in a Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/amazon-s3-policy-keys.html)
  in the *Amazon S3 User Guide*. For a complete list of Amazon S3-specific
  condition keys, see [Actions, Resources, and Condition Keys for Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/list_amazons3.html).

  ## x-amz-copy-source-if Headers

  To only copy an object under certain conditions, such as whether the `Etag`
  matches or whether the object was modified before or after a specified date, use
  the following request parameters:

    * `x-amz-copy-source-if-match`

    * `x-amz-copy-source-if-none-match`

    * `x-amz-copy-source-if-unmodified-since`

    * `x-amz-copy-source-if-modified-since`

  If both the `x-amz-copy-source-if-match` and
  `x-amz-copy-source-if-unmodified-since` headers are present in the request and
  evaluate as follows, Amazon S3 returns `200 OK` and copies the data:

    * `x-amz-copy-source-if-match` condition evaluates to true

    * `x-amz-copy-source-if-unmodified-since` condition evaluates to
  false

  If both the `x-amz-copy-source-if-none-match` and
  `x-amz-copy-source-if-modified-since` headers are present in the request and
  evaluate as follows, Amazon S3 returns the `412 Precondition Failed` response
  code:

    * `x-amz-copy-source-if-none-match` condition evaluates to false

    * `x-amz-copy-source-if-modified-since` condition evaluates to true

  All headers with the `x-amz-` prefix, including `x-amz-copy-source`, must be
  signed.

  ## Server-side encryption

  When you perform a CopyObject operation, you can optionally use the appropriate
  encryption-related headers to encrypt the object using server-side encryption
  with Amazon Web Services managed encryption keys (SSE-S3 or SSE-KMS) or a
  customer-provided encryption key. With server-side encryption, Amazon S3
  encrypts your data as it writes it to disks in its data centers and decrypts the
  data when you access it. For more information about server-side encryption, see
  [Using Server-Side Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/serv-side-encryption.html).

  If a target object uses SSE-KMS, you can enable an S3 Bucket Key for the object.
  For more information, see [Amazon S3 Bucket Keys](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-key.html) in the
  *Amazon S3 User Guide*.

  ## Access Control List (ACL)-Specific Request Headers

  When copying an object, you can optionally use headers to grant ACL-based
  permissions. By default, all objects are private. Only the owner has full access
  control. When adding a new object, you can grant permissions to individual
  Amazon Web Services accounts or to predefined groups defined by Amazon S3. These
  permissions are then added to the ACL on the object. For more information, see
  [Access Control List (ACL) Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html) and
  [Managing ACLs Using the REST API](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-using-rest-api.html).

  If the bucket that you're copying objects to uses the bucket owner enforced
  setting for S3 Object Ownership, ACLs are disabled and no longer affect
  permissions. Buckets that use this setting only accept PUT requests that don't
  specify an ACL or PUT requests that specify bucket owner full control ACLs, such
  as the `bucket-owner-full-control` canned ACL or an equivalent form of this ACL
  expressed in the XML format.

  For more information, see [ Controlling ownership of objects and disabling ACLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)
  in the *Amazon S3 User Guide*.

  If your bucket uses the bucket owner enforced setting for Object Ownership, all
  objects written to the bucket by any account will be owned by the bucket owner.

  ## Checksums

  When copying an object, if it has a checksum, that checksum will be copied to
  the new object by default. When you copy the object over, you may optionally
  specify a different checksum algorithm to use with the
  `x-amz-checksum-algorithm` header.

  ## Storage Class Options

  You can use the `CopyObject` action to change the storage class of an object
  that is already stored in Amazon S3 using the `StorageClass` parameter. For more
  information, see [Storage Classes](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html)
  in the *Amazon S3 User Guide*.

  ## Versioning

  By default, `x-amz-copy-source` identifies the current version of an object to
  copy. If the current version is a delete marker, Amazon S3 behaves as if the
  object was deleted. To copy a different version, use the `versionId`
  subresource.

  If you enable versioning on the target bucket, Amazon S3 generates a unique
  version ID for the object being copied. This version ID is different from the
  version ID of the source object. Amazon S3 returns the version ID of the copied
  object in the `x-amz-version-id` response header in the response.

  If you do not enable versioning or suspend it on the target bucket, the version
  ID that Amazon S3 generates is always null.

  If the source object's storage class is GLACIER, you must restore a copy of this
  object before you can use it as a source object for the copy operation. For more
  information, see
  [RestoreObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html).  The following operations are related to `CopyObject`:

    *
  [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)

    *
  [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) 

  For more information, see [Copying
  Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjectsExamples.html).
  """
  def copy_object(%Client{} = client, bucket, key, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}"

    {headers, input} =
      [
        {"ChecksumAlgorithm", "x-amz-checksum-algorithm"},
        {"CopySourceSSECustomerAlgorithm",
         "x-amz-copy-source-server-side-encryption-customer-algorithm"},
        {"SSECustomerKey", "x-amz-server-side-encryption-customer-key"},
        {"CopySource", "x-amz-copy-source"},
        {"GrantFullControl", "x-amz-grant-full-control"},
        {"ACL", "x-amz-acl"},
        {"ObjectLockRetainUntilDate", "x-amz-object-lock-retain-until-date"},
        {"RequestPayer", "x-amz-request-payer"},
        {"BucketKeyEnabled", "x-amz-server-side-encryption-bucket-key-enabled"},
        {"ContentType", "Content-Type"},
        {"SSECustomerKeyMD5", "x-amz-server-side-encryption-customer-key-MD5"},
        {"ObjectLockLegalHoldStatus", "x-amz-object-lock-legal-hold"},
        {"Tagging", "x-amz-tagging"},
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"},
        {"CopySourceSSECustomerKey", "x-amz-copy-source-server-side-encryption-customer-key"},
        {"WebsiteRedirectLocation", "x-amz-website-redirect-location"},
        {"ContentLanguage", "Content-Language"},
        {"SSECustomerAlgorithm", "x-amz-server-side-encryption-customer-algorithm"},
        {"ContentEncoding", "Content-Encoding"},
        {"CopySourceSSECustomerKeyMD5",
         "x-amz-copy-source-server-side-encryption-customer-key-MD5"},
        {"CopySourceIfMatch", "x-amz-copy-source-if-match"},
        {"CopySourceIfUnmodifiedSince", "x-amz-copy-source-if-unmodified-since"},
        {"Expires", "Expires"},
        {"GrantWriteACP", "x-amz-grant-write-acp"},
        {"SSEKMSEncryptionContext", "x-amz-server-side-encryption-context"},
        {"CacheControl", "Cache-Control"},
        {"ExpectedSourceBucketOwner", "x-amz-source-expected-bucket-owner"},
        {"MetadataDirective", "x-amz-metadata-directive"},
        {"StorageClass", "x-amz-storage-class"},
        {"CopySourceIfModifiedSince", "x-amz-copy-source-if-modified-since"},
        {"GrantRead", "x-amz-grant-read"},
        {"TaggingDirective", "x-amz-tagging-directive"},
        {"ObjectLockMode", "x-amz-object-lock-mode"},
        {"ContentDisposition", "Content-Disposition"},
        {"ServerSideEncryption", "x-amz-server-side-encryption"},
        {"CopySourceIfNoneMatch", "x-amz-copy-source-if-none-match"},
        {"SSEKMSKeyId", "x-amz-server-side-encryption-aws-kms-key-id"},
        {"GrantReadACP", "x-amz-grant-read-acp"}
      ]
      |> Request.build_params(input)

    query_params = []

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [
          {"x-amz-server-side-encryption-bucket-key-enabled", "BucketKeyEnabled"},
          {"x-amz-copy-source-version-id", "CopySourceVersionId"},
          {"x-amz-expiration", "Expiration"},
          {"x-amz-request-charged", "RequestCharged"},
          {"x-amz-server-side-encryption-customer-algorithm", "SSECustomerAlgorithm"},
          {"x-amz-server-side-encryption-customer-key-MD5", "SSECustomerKeyMD5"},
          {"x-amz-server-side-encryption-context", "SSEKMSEncryptionContext"},
          {"x-amz-server-side-encryption-aws-kms-key-id", "SSEKMSKeyId"},
          {"x-amz-server-side-encryption", "ServerSideEncryption"},
          {"x-amz-version-id", "VersionId"}
        ]
      )

    meta = metadata()

    Request.request_rest(client, meta, :put, url_path, query_params, headers, input, options, nil)
  end

  @doc """
  Creates a new S3 bucket.

  To create a bucket, you must register with Amazon S3 and have a valid Amazon Web
  Services Access Key ID to authenticate requests. Anonymous requests are never
  allowed to create buckets. By creating the bucket, you become the bucket owner.

  Not every string is an acceptable bucket name. For information about bucket
  naming restrictions, see [Bucket naming rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html).

  If you want to create an Amazon S3 on Outposts bucket, see [Create Bucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_CreateBucket.html).

  By default, the bucket is created in the US East (N. Virginia) Region. You can
  optionally specify a Region in the request body. You might choose a Region to
  optimize latency, minimize costs, or address regulatory requirements. For
  example, if you reside in Europe, you will probably find it advantageous to
  create buckets in the Europe (Ireland) Region. For more information, see
  [Accessing a bucket](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro).

  If you send your create bucket request to the `s3.amazonaws.com` endpoint, the
  request goes to the us-east-1 Region. Accordingly, the signature calculations in
  Signature Version 4 must use us-east-1 as the Region, even if the location
  constraint in the request specifies another Region where the bucket is to be
  created. If you create a bucket in a Region other than US East (N. Virginia),
  your application must be able to handle 307 redirect. For more information, see
  [Virtual hosting of buckets](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html).

  ## Access control lists (ACLs)

  When creating a bucket using this operation, you can optionally configure the
  bucket ACL to specify the accounts or groups that should be granted specific
  permissions on the bucket.

  If your CreateBucket request sets bucket owner enforced for S3 Object Ownership
  and specifies a bucket ACL that provides access to an external Amazon Web
  Services account, your request fails with a `400` error and returns the
  `InvalidBucketAclWithObjectOwnership` error code. For more information, see
  [Controlling object ownership](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)
  in the *Amazon S3 User Guide*.

  There are two ways to grant the appropriate permissions using the request
  headers.

    * Specify a canned ACL using the `x-amz-acl` request header. Amazon
  S3 supports a set of predefined ACLs, known as *canned ACLs*. Each canned ACL
  has a predefined set of grantees and permissions. For more information, see
  [Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#CannedACL).

    * Specify access permissions explicitly using the
  `x-amz-grant-read`, `x-amz-grant-write`, `x-amz-grant-read-acp`,
  `x-amz-grant-write-acp`, and `x-amz-grant-full-control` headers. These headers
  map to the set of permissions Amazon S3 supports in an ACL. For more
  information, see [Access control list (ACL) overview](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html).

  You specify each grantee as a type=value pair, where the type is one of the
  following:

      * `id` – if the value specified is the canonical user ID
  of an Amazon Web Services account

      * `uri` – if you are granting permissions to a
  predefined group

      * `emailAddress` – if the value specified is the email
  address of an Amazon Web Services account

  Using email addresses to specify a grantee is only supported in the following
  Amazon Web Services Regions:

     US East (N. Virginia)

     US West (N. California)

     US West (Oregon)

     Asia Pacific (Singapore)

     Asia Pacific (Sydney)

     Asia Pacific (Tokyo)

     Europe (Ireland)

     South America (São Paulo)

  For a list of all the Amazon S3 supported Regions and endpoints, see [Regions and
  Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)
  in the Amazon Web Services General Reference.

  For example, the following `x-amz-grant-read` header grants the Amazon Web
  Services accounts identified by account IDs permissions to read object data and
  its metadata:

  `x-amz-grant-read: id="11112222333", id="444455556666" `

  You can use either a canned ACL or specify access permissions explicitly. You
  cannot do both.

  ## Permissions

  In addition to `s3:CreateBucket`, the following permissions are required when
  your CreateBucket includes specific headers:

    * **ACLs** - If your `CreateBucket` request specifies ACL
  permissions and the ACL is public-read, public-read-write, authenticated-read,
  or if you specify access permissions explicitly through any other ACL, both
  `s3:CreateBucket` and `s3:PutBucketAcl` permissions are needed. If the ACL the
  `CreateBucket` request is private or doesn't specify any ACLs, only
  `s3:CreateBucket` permission is needed.

    * **Object Lock** - If `ObjectLockEnabledForBucket` is set to true
  in your `CreateBucket` request, `s3:PutBucketObjectLockConfiguration` and
  `s3:PutBucketVersioning` permissions are required.

    * **S3 Object Ownership** - If your CreateBucket request includes
  the the `x-amz-object-ownership` header, `s3:PutBucketOwnershipControls`
  permission is required.

  The following operations are related to `CreateBucket`:

    *
  [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)     *
  [DeleteBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html)
  """
  def create_bucket(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}"

    {headers, input} =
      [
        {"ACL", "x-amz-acl"},
        {"GrantFullControl", "x-amz-grant-full-control"},
        {"GrantRead", "x-amz-grant-read"},
        {"GrantReadACP", "x-amz-grant-read-acp"},
        {"GrantWrite", "x-amz-grant-write"},
        {"GrantWriteACP", "x-amz-grant-write-acp"},
        {"ObjectLockEnabledForBucket", "x-amz-bucket-object-lock-enabled"},
        {"ObjectOwnership", "x-amz-object-ownership"}
      ]
      |> Request.build_params(input)

    query_params = []

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [{"Location", "Location"}]
      )

    meta = metadata()

    Request.request_rest(client, meta, :put, url_path, query_params, headers, input, options, nil)
  end

  @doc """
  This action initiates a multipart upload and returns an upload ID.

  This upload ID is used to associate all of the parts in the specific multipart
  upload. You specify this upload ID in each of your subsequent upload part
  requests (see
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)). You also include this upload ID in the final request to either complete or abort
  the multipart upload request.

  For more information about multipart uploads, see [Multipart Upload
  Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html).

  If you have configured a lifecycle rule to abort incomplete multipart uploads,
  the upload must complete within the number of days specified in the bucket
  lifecycle configuration. Otherwise, the incomplete multipart upload becomes
  eligible for an abort action and Amazon S3 aborts the multipart upload. For more
  information, see [Aborting Incomplete Multipart Uploads Using a Bucket Lifecycle Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuoverview.html#mpu-abort-incomplete-mpu-lifecycle-config).

  For information about the permissions required to use the multipart upload API,
  see [Multipart Upload and Permissions](https://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html).

  For request signing, multipart upload is just a series of regular requests. You
  initiate a multipart upload, send one or more requests to upload parts, and then
  complete the multipart upload process. You sign each request individually. There
  is nothing special about signing multipart upload requests. For more information
  about signing, see [Authenticating Requests (Amazon Web Services Signature Version
  4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html).

  After you initiate a multipart upload and upload one or more parts, to stop
  being charged for storing the uploaded parts, you must either complete or abort
  the multipart upload. Amazon S3 frees up the space used to store the parts and
  stop charging you for storing them only after you either complete or abort a
  multipart upload.

  You can optionally request server-side encryption. For server-side encryption,
  Amazon S3 encrypts your data as it writes it to disks in its data centers and
  decrypts it when you access it. You can provide your own encryption key, or use
  Amazon Web Services KMS keys or Amazon S3-managed encryption keys. If you choose
  to provide your own encryption key, the request headers you provide in
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) and
  [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
  requests must match the headers you used in the request to initiate the upload
  by using `CreateMultipartUpload`.

  To perform a multipart upload with encryption using an Amazon Web Services KMS
  key, the requester must have permission to the `kms:Decrypt` and
  `kms:GenerateDataKey*` actions on the key. These permissions are required
  because Amazon S3 must decrypt and read data from the encrypted file parts
  before it completes the multipart upload. For more information, see [Multipart upload API and
  permissions](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html#mpuAndPermissions)
  in the *Amazon S3 User Guide*.

  If your Identity and Access Management (IAM) user or role is in the same Amazon
  Web Services account as the KMS key, then you must have these permissions on the
  key policy. If your IAM user or role belongs to a different account than the
  key, then you must have the permissions on both the key policy and your IAM user
  or role.

  For more information, see [Protecting Data Using Server-Side Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/serv-side-encryption.html).

  ## Definitions

  ### Access Permissions

  When copying an object, you can optionally specify the accounts or groups that
  should be granted specific permissions on the new object. There are two ways to
  grant the permissions using the request headers:

     Specify a canned ACL with the `x-amz-acl` request header. For more
  information, see [Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#CannedACL).

     Specify access permissions explicitly with the `x-amz-grant-read`,
  `x-amz-grant-read-acp`, `x-amz-grant-write-acp`, and `x-amz-grant-full-control`
  headers. These parameters map to the set of permissions that Amazon S3 supports
  in an ACL. For more information, see [Access Control List (ACL) Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html).

  You can use either a canned ACL or specify access permissions explicitly. You
  cannot do both.

  ### Server-Side- Encryption-Specific Request Headers

  You can optionally tell Amazon S3 to encrypt data at rest using server-side
  encryption. Server-side encryption is for data encryption at rest. Amazon S3
  encrypts your data as it writes it to disks in its data centers and decrypts it
  when you access it. The option you use depends on whether you want to use Amazon
  Web Services managed encryption keys or provide your own encryption key.

     Use encryption keys managed by Amazon S3 or customer managed key
  stored in Amazon Web Services Key Management Service (Amazon Web Services KMS) –
  If you want Amazon Web Services to manage the keys used to encrypt data, specify
  the following headers in the request.

       `x-amz-server-side-encryption`

       `x-amz-server-side-encryption-aws-kms-key-id`

       `x-amz-server-side-encryption-context`

  If you specify `x-amz-server-side-encryption:aws:kms`, but don't provide
  `x-amz-server-side-encryption-aws-kms-key-id`, Amazon S3 uses the Amazon Web
  Services managed key in Amazon Web Services KMS to protect the data.

  All GET and PUT requests for an object protected by Amazon Web Services KMS fail
  if you don't make them with SSL or by using SigV4.

  For more information about server-side encryption with KMS key (SSE-KMS), see
  [Protecting Data Using Server-Side Encryption with KMS keys](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html).

     Use customer-provided encryption keys – If you want to manage your
  own encryption keys, provide all the following headers in the request.

       `x-amz-server-side-encryption-customer-algorithm`

       `x-amz-server-side-encryption-customer-key`

       `x-amz-server-side-encryption-customer-key-MD5`

  For more information about server-side encryption with KMS keys (SSE-KMS), see
  [Protecting Data Using Server-Side Encryption with KMS keys](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html).

  ### Access-Control-List (ACL)-Specific Request Headers

  You also can use the following access control–related headers with this
  operation. By default, all objects are private. Only the owner has full access
  control. When adding a new object, you can grant permissions to individual
  Amazon Web Services accounts or to predefined groups defined by Amazon S3. These
  permissions are then added to the access control list (ACL) on the object. For
  more information, see [Using ACLs](https://docs.aws.amazon.com/AmazonS3/latest/dev/S3_ACLs_UsingACLs.html).
  With this operation, you can grant access permissions using one of the following
  two methods:

     Specify a canned ACL (`x-amz-acl`) — Amazon S3 supports a set of
  predefined ACLs, known as *canned ACLs*. Each canned ACL has a predefined set of
  grantees and permissions. For more information, see [Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#CannedACL).

     Specify access permissions explicitly — To explicitly grant access
  permissions to specific Amazon Web Services accounts or groups, use the
  following headers. Each header maps to specific permissions that Amazon S3
  supports in an ACL. For more information, see [Access Control List (ACL) Overview](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html). In
  the header, you specify a list of grantees who get the specific permission. To
  grant permissions explicitly, use:

       `x-amz-grant-read`

       `x-amz-grant-write`

       `x-amz-grant-read-acp`

       `x-amz-grant-write-acp`

       `x-amz-grant-full-control`

  You specify each grantee as a type=value pair, where the type is one of the
  following:

       `id` – if the value specified is the canonical user ID
  of an Amazon Web Services account

       `uri` – if you are granting permissions to a predefined
  group

       `emailAddress` – if the value specified is the email
  address of an Amazon Web Services account

  Using email addresses to specify a grantee is only supported in the following
  Amazon Web Services Regions:

     US East (N. Virginia)

     US West (N. California)

     US West (Oregon)

     Asia Pacific (Singapore)

     Asia Pacific (Sydney)

     Asia Pacific (Tokyo)

     Europe (Ireland)

     South America (São Paulo)

  For a list of all the Amazon S3 supported Regions and endpoints, see [Regions and
  Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region)
  in the Amazon Web Services General Reference.

  For example, the following `x-amz-grant-read` header grants the Amazon Web
  Services accounts identified by account IDs permissions to read object data and
  its metadata:

  `x-amz-grant-read: id="11112222333", id="444455556666" `

  The following operations are related to `CreateMultipartUpload`:

    *
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)     *
  [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)

    *
  [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)     *
  [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)

    *
  [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)
  """
  def create_multipart_upload(%Client{} = client, bucket, key, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}?uploads"

    {headers, input} =
      [
        {"ACL", "x-amz-acl"},
        {"BucketKeyEnabled", "x-amz-server-side-encryption-bucket-key-enabled"},
        {"CacheControl", "Cache-Control"},
        {"ChecksumAlgorithm", "x-amz-checksum-algorithm"},
        {"ContentDisposition", "Content-Disposition"},
        {"ContentEncoding", "Content-Encoding"},
        {"ContentLanguage", "Content-Language"},
        {"ContentType", "Content-Type"},
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"},
        {"Expires", "Expires"},
        {"GrantFullControl", "x-amz-grant-full-control"},
        {"GrantRead", "x-amz-grant-read"},
        {"GrantReadACP", "x-amz-grant-read-acp"},
        {"GrantWriteACP", "x-amz-grant-write-acp"},
        {"ObjectLockLegalHoldStatus", "x-amz-object-lock-legal-hold"},
        {"ObjectLockMode", "x-amz-object-lock-mode"},
        {"ObjectLockRetainUntilDate", "x-amz-object-lock-retain-until-date"},
        {"RequestPayer", "x-amz-request-payer"},
        {"SSECustomerAlgorithm", "x-amz-server-side-encryption-customer-algorithm"},
        {"SSECustomerKey", "x-amz-server-side-encryption-customer-key"},
        {"SSECustomerKeyMD5", "x-amz-server-side-encryption-customer-key-MD5"},
        {"SSEKMSEncryptionContext", "x-amz-server-side-encryption-context"},
        {"SSEKMSKeyId", "x-amz-server-side-encryption-aws-kms-key-id"},
        {"ServerSideEncryption", "x-amz-server-side-encryption"},
        {"StorageClass", "x-amz-storage-class"},
        {"Tagging", "x-amz-tagging"},
        {"WebsiteRedirectLocation", "x-amz-website-redirect-location"}
      ]
      |> Request.build_params(input)

    query_params = []

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [
          {"x-amz-abort-date", "AbortDate"},
          {"x-amz-abort-rule-id", "AbortRuleId"},
          {"x-amz-server-side-encryption-bucket-key-enabled", "BucketKeyEnabled"},
          {"x-amz-checksum-algorithm", "ChecksumAlgorithm"},
          {"x-amz-request-charged", "RequestCharged"},
          {"x-amz-server-side-encryption-customer-algorithm", "SSECustomerAlgorithm"},
          {"x-amz-server-side-encryption-customer-key-MD5", "SSECustomerKeyMD5"},
          {"x-amz-server-side-encryption-context", "SSEKMSEncryptionContext"},
          {"x-amz-server-side-encryption-aws-kms-key-id", "SSEKMSKeyId"},
          {"x-amz-server-side-encryption", "ServerSideEncryption"}
        ]
      )

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :post,
      url_path,
      query_params,
      headers,
      input,
      options,
      nil
    )
  end

  @doc """
  Deletes the S3 bucket.

  All objects (including all object versions and delete markers) in the bucket
  must be deleted before the bucket itself can be deleted.

  ## Related Resources

    *
  [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)     *
  [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html)
  """
  def delete_bucket(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes an analytics configuration for the bucket (specified by the analytics
  configuration ID).

  To use this operation, you must have permissions to perform the
  `s3:PutAnalyticsConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  For information about the Amazon S3 analytics feature, see [Amazon S3 Analytics – Storage Class
  Analysis](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html).

  The following operations are related to `DeleteBucketAnalyticsConfiguration`:

    *
  [GetBucketAnalyticsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketAnalyticsConfiguration.html)     *
  [ListBucketAnalyticsConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketAnalyticsConfigurations.html)

    *
  [PutBucketAnalyticsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAnalyticsConfiguration.html)
  """
  def delete_bucket_analytics_configuration(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?analytics"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"Id", "id"}
      ]
      |> Request.build_params(input)

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes the `cors` configuration information set for the bucket.

  To use this operation, you must have permission to perform the
  `s3:PutBucketCORS` action. The bucket owner has this permission by default and
  can grant this permission to others.

  For information about `cors`, see [Enabling Cross-Origin Resource Sharing](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html) in the
  *Amazon S3 User Guide*.

  ## Related Resources:

    *
  [PutBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html)     *
  [RESTOPTIONSobject](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTOPTIONSobject.html)
  """
  def delete_bucket_cors(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?cors"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  This implementation of the DELETE action removes default encryption from the
  bucket.

  For information about the Amazon S3 default encryption feature, see [Amazon S3 Default Bucket
  Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html)
  in the *Amazon S3 User Guide*.

  To use this operation, you must have permissions to perform the
  `s3:PutEncryptionConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html)
  in the *Amazon S3 User Guide*.

  ## Related Resources

    *
  [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)     *
  [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html)
  """
  def delete_bucket_encryption(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?encryption"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes the S3 Intelligent-Tiering configuration from the specified bucket.

  The S3 Intelligent-Tiering storage class is designed to optimize storage costs
  by automatically moving data to the most cost-effective storage access tier,
  without performance impact or operational overhead. S3 Intelligent-Tiering
  delivers automatic cost savings in three low latency and high throughput access
  tiers. To get the lowest storage cost on data that can be accessed in minutes to
  hours, you can choose to activate additional archiving capabilities.

  The S3 Intelligent-Tiering storage class is the ideal storage class for data
  with unknown, changing, or unpredictable access patterns, independent of object
  size or retention period. If the size of an object is less than 128 KB, it is
  not monitored and not eligible for auto-tiering. Smaller objects can be stored,
  but they are always charged at the Frequent Access tier rates in the S3
  Intelligent-Tiering storage class.

  For more information, see [Storage class for automatically optimizing frequently and infrequently accessed
  objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html#sc-dynamic-data-access).

  Operations related to `DeleteBucketIntelligentTieringConfiguration` include:

    *
  [GetBucketIntelligentTieringConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketIntelligentTieringConfiguration.html)     *
  [PutBucketIntelligentTieringConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketIntelligentTieringConfiguration.html)

    *
  [ListBucketIntelligentTieringConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketIntelligentTieringConfigurations.html)
  """
  def delete_bucket_intelligent_tiering_configuration(
        %Client{} = client,
        bucket,
        input,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?intelligent-tiering"
    headers = []

    {query_params, input} =
      [
        {"Id", "id"}
      ]
      |> Request.build_params(input)

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes an inventory configuration (identified by the inventory ID) from the
  bucket.

  To use this operation, you must have permissions to perform the
  `s3:PutInventoryConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  For information about the Amazon S3 inventory feature, see [Amazon S3 Inventory](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html).

  Operations related to `DeleteBucketInventoryConfiguration` include:

    *
  [GetBucketInventoryConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketInventoryConfiguration.html)     *
  [PutBucketInventoryConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketInventoryConfiguration.html)

    *
  [ListBucketInventoryConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketInventoryConfigurations.html)
  """
  def delete_bucket_inventory_configuration(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?inventory"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"Id", "id"}
      ]
      |> Request.build_params(input)

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes the lifecycle configuration from the specified bucket.

  Amazon S3 removes all the lifecycle configuration rules in the lifecycle
  subresource associated with the bucket. Your objects never expire, and Amazon S3
  no longer automatically deletes any objects on the basis of rules contained in
  the deleted lifecycle configuration.

  To use this operation, you must have permission to perform the
  `s3:PutLifecycleConfiguration` action. By default, the bucket owner has this
  permission and the bucket owner can grant this permission to others.

  There is usually some time lag before lifecycle configuration deletion is fully
  propagated to all the Amazon S3 systems.

  For more information about the object expiration, see [Elements to Describe Lifecycle
  Actions](https://docs.aws.amazon.com/AmazonS3/latest/dev/intro-lifecycle-rules.html#intro-lifecycle-rules-actions).

  Related actions include:

    *
  [PutBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html)     *
  [GetBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html)
  """
  def delete_bucket_lifecycle(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?lifecycle"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes a metrics configuration for the Amazon CloudWatch request metrics
  (specified by the metrics configuration ID) from the bucket.

  Note that this doesn't include the daily storage metrics.

  To use this operation, you must have permissions to perform the
  `s3:PutMetricsConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  For information about CloudWatch request metrics for Amazon S3, see [Monitoring Metrics with Amazon
  CloudWatch](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html).

  The following operations are related to `DeleteBucketMetricsConfiguration`:

    *
  [GetBucketMetricsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketMetricsConfiguration.html)     *
  [PutBucketMetricsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketMetricsConfiguration.html)

    *
  [ListBucketMetricsConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketMetricsConfigurations.html)     * [Monitoring Metrics with Amazon
  CloudWatch](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html)
  """
  def delete_bucket_metrics_configuration(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?metrics"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"Id", "id"}
      ]
      |> Request.build_params(input)

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Removes `OwnershipControls` for an Amazon S3 bucket.

  To use this operation, you must have the `s3:PutBucketOwnershipControls`
  permission. For more information about Amazon S3 permissions, see [Specifying Permissions in a
  Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html).

  For information about Amazon S3 Object Ownership, see [Using Object Ownership](https://docs.aws.amazon.com/AmazonS3/latest/dev/about-object-ownership.html).

  The following operations are related to `DeleteBucketOwnershipControls`:

    * `GetBucketOwnershipControls`

    * `PutBucketOwnershipControls`
  """
  def delete_bucket_ownership_controls(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?ownershipControls"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  This implementation of the DELETE action uses the policy subresource to delete
  the policy of a specified bucket.

  If you are using an identity other than the root user of the Amazon Web Services
  account that owns the bucket, the calling identity must have the
  `DeleteBucketPolicy` permissions on the specified bucket and belong to the
  bucket owner's account to use this operation.

  If you don't have `DeleteBucketPolicy` permissions, Amazon S3 returns a `403
  Access Denied` error. If you have the correct permissions, but you're not using
  an identity that belongs to the bucket owner's account, Amazon S3 returns a `405
  Method Not Allowed` error.

  As a security precaution, the root user of the Amazon Web Services account that
  owns a bucket can always use this operation, even if the policy explicitly
  denies the root user the ability to perform this action.

  For more information about bucket policies, see [Using Bucket Policies and UserPolicies](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html).

  The following operations are related to `DeleteBucketPolicy`

    *
  [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)     *
  [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html)
  """
  def delete_bucket_policy(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?policy"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes the replication configuration from the bucket.

  To use this operation, you must have permissions to perform the
  `s3:PutReplicationConfiguration` action. The bucket owner has these permissions
  by default and can grant it to others. For more information about permissions,
  see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  It can take a while for the deletion of a replication configuration to fully
  propagate.

  For information about replication configuration, see
  [Replication](https://docs.aws.amazon.com/AmazonS3/latest/dev/replication.html) in the *Amazon S3 User Guide*.

  The following operations are related to `DeleteBucketReplication`:

    *
  [PutBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html)

    *
  [GetBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html)
  """
  def delete_bucket_replication(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?replication"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Deletes the tags from the bucket.

  To use this operation, you must have permission to perform the
  `s3:PutBucketTagging` action. By default, the bucket owner has this permission
  and can grant this permission to others.

  The following operations are related to `DeleteBucketTagging`:

    *
  [GetBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html)     *
  [PutBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html)
  """
  def delete_bucket_tagging(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?tagging"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  This action removes the website configuration for a bucket.

  Amazon S3 returns a `200 OK` response upon successfully deleting a website
  configuration on the specified bucket. You will get a `200 OK` response if the
  website configuration you are trying to delete does not exist on the bucket.
  Amazon S3 returns a `404` response if the bucket specified in the request does
  not exist.

  This DELETE action requires the `S3:DeleteBucketWebsite` permission. By default,
  only the bucket owner can delete the website configuration attached to a bucket.
  However, bucket owners can grant other users permission to delete the website
  configuration by writing a bucket policy granting them the
  `S3:DeleteBucketWebsite` permission.

  For more information about hosting websites, see [Hosting Websites on Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html).

  The following operations are related to `DeleteBucketWebsite`:

    *
  [GetBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketWebsite.html)     *
  [PutBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketWebsite.html)
  """
  def delete_bucket_website(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?website"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Removes the null version (if there is one) of an object and inserts a delete
  marker, which becomes the latest version of the object.

  If there isn't a null version, Amazon S3 does not remove any objects but will
  still respond that the command was successful.

  To remove a specific version, you must be the bucket owner and you must use the
  version Id subresource. Using this subresource permanently deletes the version.
  If the object deleted is a delete marker, Amazon S3 sets the response header,
  `x-amz-delete-marker`, to true.

  If the object you want to delete is in a bucket where the bucket versioning
  configuration is MFA Delete enabled, you must include the `x-amz-mfa` request
  header in the DELETE `versionId` request. Requests that include `x-amz-mfa` must
  use HTTPS.

  For more information about MFA Delete, see [Using MFA Delete](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMFADelete.html). To
  see sample requests that use versioning, see [Sample Request](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html#ExampleVersionObjectDelete).

  You can delete objects by explicitly calling DELETE Object or configure its
  lifecycle
  ([PutBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycle.html)) to enable Amazon S3 to remove them for you. If you want to block users or
  accounts from removing or deleting objects from your bucket, you must deny them
  the `s3:DeleteObject`, `s3:DeleteObjectVersion`, and
  `s3:PutLifeCycleConfiguration` actions.

  The following action is related to `DeleteObject`:

    *
  [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
  """
  def delete_object(%Client{} = client, bucket, key, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}"

    {headers, input} =
      [
        {"BypassGovernanceRetention", "x-amz-bypass-governance-retention"},
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"},
        {"MFA", "x-amz-mfa"},
        {"RequestPayer", "x-amz-request-payer"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"VersionId", "versionId"}
      ]
      |> Request.build_params(input)

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [
          {"x-amz-delete-marker", "DeleteMarker"},
          {"x-amz-request-charged", "RequestCharged"},
          {"x-amz-version-id", "VersionId"}
        ]
      )

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  Removes the entire tag set from the specified object.

  For more information about managing object tags, see [ Object Tagging](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-tagging.html).

  To use this operation, you must have permission to perform the
  `s3:DeleteObjectTagging` action.

  To delete tags of a specific object version, add the `versionId` query parameter
  in the request. You will need permission for the `s3:DeleteObjectVersionTagging`
  action.

  The following operations are related to `DeleteBucketMetricsConfiguration`:

    *
  [PutObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html)     *
  [GetObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html)
  """
  def delete_object_tagging(%Client{} = client, bucket, key, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}?tagging"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    {query_params, input} =
      [
        {"VersionId", "versionId"}
      ]
      |> Request.build_params(input)

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [{"x-amz-version-id", "VersionId"}]
      )

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  This action enables you to delete multiple objects from a bucket using a single
  HTTP request.

  If you know the object keys that you want to delete, then this action provides a
  suitable alternative to sending individual delete requests, reducing per-request
  overhead.

  The request contains a list of up to 1000 keys that you want to delete. In the
  XML, you provide the object key names, and optionally, version IDs if you want
  to delete a specific version of the object from a versioning-enabled bucket. For
  each key, Amazon S3 performs a delete action and returns the result of that
  delete, success, or failure, in the response. Note that if the object specified
  in the request is not found, Amazon S3 returns the result as deleted.

  The action supports two modes for the response: verbose and quiet. By default,
  the action uses verbose mode in which the response includes the result of
  deletion of each key in your request. In quiet mode the response includes only
  keys where the delete action encountered an error. For a successful deletion,
  the action does not return any information about the delete in the response
  body.

  When performing this action on an MFA Delete enabled bucket, that attempts to
  delete any versioned objects, you must include an MFA token. If you do not
  provide one, the entire request will fail, even if there are non-versioned
  objects you are trying to delete. If you provide an invalid token, whether there
  are versioned keys in the request or not, the entire Multi-Object Delete request
  will fail. For information about MFA Delete, see [ MFA Delete](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html#MultiFactorAuthenticationDelete).

  Finally, the Content-MD5 header is required for all Multi-Object Delete
  requests. Amazon S3 uses the header value to ensure that your request body has
  not been altered in transit.

  The following operations are related to `DeleteObjects`:

    *
  [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)     *
  [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)

    *
  [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)     *
  [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)

    *
  [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)
  """
  def delete_objects(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?delete"

    {headers, input} =
      [
        {"BypassGovernanceRetention", "x-amz-bypass-governance-retention"},
        {"ChecksumAlgorithm", "x-amz-sdk-checksum-algorithm"},
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"},
        {"MFA", "x-amz-mfa"},
        {"RequestPayer", "x-amz-request-payer"}
      ]
      |> Request.build_params(input)

    query_params = []

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [{"x-amz-request-charged", "RequestCharged"}]
      )

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :post,
      url_path,
      query_params,
      headers,
      input,
      options,
      nil
    )
  end

  @doc """
  Removes the `PublicAccessBlock` configuration for an Amazon S3 bucket.

  To use this operation, you must have the `s3:PutBucketPublicAccessBlock`
  permission. For more information about permissions, see [Permissions Related to Bucket Subresource
  Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  The following operations are related to `DeletePublicAccessBlock`:

    * [Using Amazon S3 Block Public Access](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html)

    *
  [GetPublicAccessBlock](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetPublicAccessBlock.html)     *
  [PutPublicAccessBlock](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutPublicAccessBlock.html)

    *
  [GetBucketPolicyStatus](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicyStatus.html)
  """
  def delete_public_access_block(%Client{} = client, bucket, input, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?publicAccessBlock"

    {headers, input} =
      [
        {"ExpectedBucketOwner", "x-amz-expected-bucket-owner"}
      ]
      |> Request.build_params(input)

    query_params = []

    meta = metadata()

    Request.request_rest(
      client,
      meta,
      :delete,
      url_path,
      query_params,
      headers,
      input,
      options,
      204
    )
  end

  @doc """
  This implementation of the GET action uses the `accelerate` subresource to
  return the Transfer Acceleration state of a bucket, which is either `Enabled` or
  `Suspended`.

  Amazon S3 Transfer Acceleration is a bucket-level feature that enables you to
  perform faster data transfers to and from Amazon S3.

  To use this operation, you must have permission to perform the
  `s3:GetAccelerateConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html)
  in the *Amazon S3 User Guide*.

  You set the Transfer Acceleration state of an existing bucket to `Enabled` or
  `Suspended` by using the
  [PutBucketAccelerateConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAccelerateConfiguration.html) operation.

  A GET `accelerate` request does not return a state value for a bucket that has
  no transfer acceleration state. A bucket has no Transfer Acceleration state if a
  state has never been set on the bucket.

  For more information about transfer acceleration, see [Transfer
  Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html)
  in the Amazon S3 User Guide.

  ## Related Resources

    *
  [PutBucketAccelerateConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAccelerateConfiguration.html)
  """
  def get_bucket_accelerate_configuration(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?accelerate"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  This implementation of the `GET` action uses the `acl` subresource to return the
  access control list (ACL) of a bucket.

  To use `GET` to return the ACL of the bucket, you must have `READ_ACP` access to
  the bucket. If `READ_ACP` permission is granted to the anonymous user, you can
  return the ACL of the bucket without using an authorization header.

  If your bucket uses the bucket owner enforced setting for S3 Object Ownership,
  requests to read ACLs are still supported and return the
  `bucket-owner-full-control` ACL with the owner being the account that created
  the bucket. For more information, see [ Controlling object ownership and disabling
  ACLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)
  in the *Amazon S3 User Guide*.

  ## Related Resources

    *
  [ListObjects](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html)
  """
  def get_bucket_acl(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?acl"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  This implementation of the GET action returns an analytics configuration
  (identified by the analytics configuration ID) from the bucket.

  To use this operation, you must have permissions to perform the
  `s3:GetAnalyticsConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [ Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html)
  in the *Amazon S3 User Guide*.

  For information about Amazon S3 analytics feature, see [Amazon S3 Analytics – Storage Class
  Analysis](https://docs.aws.amazon.com/AmazonS3/latest/dev/analytics-storage-class.html)
  in the *Amazon S3 User Guide*.

  ## Related Resources

    *
  [DeleteBucketAnalyticsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketAnalyticsConfiguration.html)     *
  [ListBucketAnalyticsConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketAnalyticsConfigurations.html)

    *
  [PutBucketAnalyticsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketAnalyticsConfiguration.html)
  """
  def get_bucket_analytics_configuration(
        %Client{} = client,
        bucket,
        id,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?analytics"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    query_params =
      if !is_nil(id) do
        [{"id", id} | query_params]
      else
        query_params
      end

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the Cross-Origin Resource Sharing (CORS) configuration information set
  for the bucket.

  To use this operation, you must have permission to perform the
  `s3:GetBucketCORS` action. By default, the bucket owner has this permission and
  can grant it to others.

  For more information about CORS, see [ Enabling Cross-Origin Resource Sharing](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html).

  The following operations are related to `GetBucketCors`:

    *
  [PutBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketCors.html)     *
  [DeleteBucketCors](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketCors.html)
  """
  def get_bucket_cors(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?cors"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the default encryption configuration for an Amazon S3 bucket.

  If the bucket does not have a default encryption configuration,
  GetBucketEncryption returns `ServerSideEncryptionConfigurationNotFoundError`.

  For information about the Amazon S3 default encryption feature, see [Amazon S3 Default Bucket
  Encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html).

  To use this operation, you must have permission to perform the
  `s3:GetEncryptionConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  The following operations are related to `GetBucketEncryption`:

    *
  [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)     *
  [DeleteBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html)
  """
  def get_bucket_encryption(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?encryption"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Gets the S3 Intelligent-Tiering configuration from the specified bucket.

  The S3 Intelligent-Tiering storage class is designed to optimize storage costs
  by automatically moving data to the most cost-effective storage access tier,
  without performance impact or operational overhead. S3 Intelligent-Tiering
  delivers automatic cost savings in three low latency and high throughput access
  tiers. To get the lowest storage cost on data that can be accessed in minutes to
  hours, you can choose to activate additional archiving capabilities.

  The S3 Intelligent-Tiering storage class is the ideal storage class for data
  with unknown, changing, or unpredictable access patterns, independent of object
  size or retention period. If the size of an object is less than 128 KB, it is
  not monitored and not eligible for auto-tiering. Smaller objects can be stored,
  but they are always charged at the Frequent Access tier rates in the S3
  Intelligent-Tiering storage class.

  For more information, see [Storage class for automatically optimizing frequently and infrequently accessed
  objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html#sc-dynamic-data-access).

  Operations related to `GetBucketIntelligentTieringConfiguration` include:

    *
  [DeleteBucketIntelligentTieringConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketIntelligentTieringConfiguration.html)     *
  [PutBucketIntelligentTieringConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketIntelligentTieringConfiguration.html)

    *
  [ListBucketIntelligentTieringConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketIntelligentTieringConfigurations.html)
  """
  def get_bucket_intelligent_tiering_configuration(%Client{} = client, bucket, id, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?intelligent-tiering"
    headers = []
    query_params = []

    query_params =
      if !is_nil(id) do
        [{"id", id} | query_params]
      else
        query_params
      end

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns an inventory configuration (identified by the inventory configuration
  ID) from the bucket.

  To use this operation, you must have permissions to perform the
  `s3:GetInventoryConfiguration` action. The bucket owner has this permission by
  default and can grant this permission to others. For more information about
  permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  For information about the Amazon S3 inventory feature, see [Amazon S3 Inventory](https://docs.aws.amazon.com/AmazonS3/latest/dev/storage-inventory.html).

  The following operations are related to `GetBucketInventoryConfiguration`:

    *
  [DeleteBucketInventoryConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketInventoryConfiguration.html)     *
  [ListBucketInventoryConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketInventoryConfigurations.html)

    *
  [PutBucketInventoryConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketInventoryConfiguration.html)
  """
  def get_bucket_inventory_configuration(
        %Client{} = client,
        bucket,
        id,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?inventory"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    query_params =
      if !is_nil(id) do
        [{"id", id} | query_params]
      else
        query_params
      end

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  For an updated version of this API, see
  [GetBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html).  If you configured a bucket lifecycle using the `filter` element, you should see
  the updated version of this topic. This topic is provided for backward
  compatibility.

  Returns the lifecycle configuration information set on the bucket. For
  information about lifecycle configuration, see [Object Lifecycle
  Management](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html).

  To use this operation, you must have permission to perform the
  `s3:GetLifecycleConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  `GetBucketLifecycle` has the following special error:

    * Error code: `NoSuchLifecycleConfiguration`

      * Description: The lifecycle configuration does not
  exist.

      * HTTP Status Code: 404 Not Found

      * SOAP Fault Code Prefix: Client

  The following operations are related to `GetBucketLifecycle`:

    *
  [GetBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html)     *
  [PutBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycle.html)

    *
  [DeleteBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketLifecycle.html)
  """
  def get_bucket_lifecycle(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?lifecycle"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Bucket lifecycle configuration now supports specifying a lifecycle rule using an
  object key name prefix, one or more object tags, or a combination of both.

  Accordingly, this section describes the latest API. The response describes the
  new filter element that you can use to specify a filter to select a subset of
  objects to which the rule applies. If you are using a previous version of the
  lifecycle configuration, it still works. For the earlier action, see
  [GetBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycle.html). 
  Returns the lifecycle configuration information set on the bucket. For
  information about lifecycle configuration, see [Object Lifecycle
  Management](https://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html).

  To use this operation, you must have permission to perform the
  `s3:GetLifecycleConfiguration` action. The bucket owner has this permission, by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  `GetBucketLifecycleConfiguration` has the following special error:

    * Error code: `NoSuchLifecycleConfiguration`

      * Description: The lifecycle configuration does not
  exist.

      * HTTP Status Code: 404 Not Found

      * SOAP Fault Code Prefix: Client

  The following operations are related to `GetBucketLifecycleConfiguration`:

    *
  [GetBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycle.html)     *
  [PutBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycle.html)

    *
  [DeleteBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketLifecycle.html)
  """
  def get_bucket_lifecycle_configuration(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?lifecycle"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the Region the bucket resides in.

  You set the bucket's Region using the `LocationConstraint` request parameter in
  a `CreateBucket` request. For more information, see
  [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html).  To use this implementation of the operation, you must be the bucket owner.

  To use this API against an access point, provide the alias of the access point
  in place of the bucket name.

  The following operations are related to `GetBucketLocation`:

    *
  [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)

    *
  [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)
  """
  def get_bucket_location(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?location"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the logging status of a bucket and the permissions users have to view
  and modify that status.

  To use GET, you must be the bucket owner.

  The following operations are related to `GetBucketLogging`:

    *
  [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)     *
  [PutBucketLogging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLogging.html)
  """
  def get_bucket_logging(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?logging"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Gets a metrics configuration (specified by the metrics configuration ID) from
  the bucket.

  Note that this doesn't include the daily storage metrics.

  To use this operation, you must have permissions to perform the
  `s3:GetMetricsConfiguration` action. The bucket owner has this permission by
  default. The bucket owner can grant this permission to others. For more
  information about permissions, see [Permissions Related to Bucket Subresource Operations](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-bucket-subresources)
  and [Managing Access Permissions to Your Amazon S3 Resources](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-access-control.html).

  For information about CloudWatch request metrics for Amazon S3, see [Monitoring Metrics with Amazon
  CloudWatch](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html).

  The following operations are related to `GetBucketMetricsConfiguration`:

    *
  [PutBucketMetricsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketMetricsConfiguration.html)     *
  [DeleteBucketMetricsConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketMetricsConfiguration.html)

    *
  [ListBucketMetricsConfigurations](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBucketMetricsConfigurations.html)     * [Monitoring Metrics with Amazon
  CloudWatch](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html)
  """
  def get_bucket_metrics_configuration(
        %Client{} = client,
        bucket,
        id,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?metrics"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    query_params =
      if !is_nil(id) do
        [{"id", id} | query_params]
      else
        query_params
      end

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  No longer used, see
  [GetBucketNotificationConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotificationConfiguration.html).
  """
  def get_bucket_notification(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?notification"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the notification configuration of a bucket.

  If notifications are not enabled on the bucket, the action returns an empty
  `NotificationConfiguration` element.

  By default, you must be the bucket owner to read the notification configuration
  of a bucket. However, the bucket owner can use a bucket policy to grant
  permission to other users to read this configuration with the
  `s3:GetBucketNotification` permission.

  For more information about setting and reading the notification configuration on
  a bucket, see [Setting Up Notification of Bucket Events](https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html).
  For more information about bucket policies, see [Using Bucket Policies](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html).

  The following action is related to `GetBucketNotification`:

    *
  [PutBucketNotification](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotification.html)
  """
  def get_bucket_notification_configuration(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?notification"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Retrieves `OwnershipControls` for an Amazon S3 bucket.

  To use this operation, you must have the `s3:GetBucketOwnershipControls`
  permission. For more information about Amazon S3 permissions, see [Specifying permissions in a
  policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html).

  For information about Amazon S3 Object Ownership, see [Using Object Ownership](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html).

  The following operations are related to `GetBucketOwnershipControls`:

    * `PutBucketOwnershipControls`

    * `DeleteBucketOwnershipControls`
  """
  def get_bucket_ownership_controls(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?ownershipControls"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the policy of a specified bucket.

  If you are using an identity other than the root user of the Amazon Web Services
  account that owns the bucket, the calling identity must have the
  `GetBucketPolicy` permissions on the specified bucket and belong to the bucket
  owner's account in order to use this operation.

  If you don't have `GetBucketPolicy` permissions, Amazon S3 returns a `403 Access
  Denied` error. If you have the correct permissions, but you're not using an
  identity that belongs to the bucket owner's account, Amazon S3 returns a `405
  Method Not Allowed` error.

  As a security precaution, the root user of the Amazon Web Services account that
  owns a bucket can always use this operation, even if the policy explicitly
  denies the root user the ability to perform this action.

  For more information about bucket policies, see [Using Bucket Policies and User Policies](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html).

  The following action is related to `GetBucketPolicy`:

    *
  [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)
  """
  def get_bucket_policy(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?policy"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Retrieves the policy status for an Amazon S3 bucket, indicating whether the
  bucket is public.

  In order to use this operation, you must have the `s3:GetBucketPolicyStatus`
  permission. For more information about Amazon S3 permissions, see [Specifying Permissions in a
  Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html).

  For more information about when Amazon S3 considers a bucket public, see [The Meaning of
  "Public"](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html#access-control-block-public-access-policy-status).

  The following operations are related to `GetBucketPolicyStatus`:

    * [Using Amazon S3 Block Public Access](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html)

    *
  [GetPublicAccessBlock](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetPublicAccessBlock.html)     *
  [PutPublicAccessBlock](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutPublicAccessBlock.html)

    *
  [DeletePublicAccessBlock](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeletePublicAccessBlock.html)
  """
  def get_bucket_policy_status(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?policyStatus"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the replication configuration of a bucket.

  It can take a while to propagate the put or delete a replication configuration
  to all Amazon S3 systems. Therefore, a get request soon after put or delete can
  return a wrong result.

  For information about replication configuration, see
  [Replication](https://docs.aws.amazon.com/AmazonS3/latest/dev/replication.html) in the *Amazon S3 User Guide*.

  This action requires permissions for the `s3:GetReplicationConfiguration`
  action. For more information about permissions, see [Using Bucket Policies and
  User
  Policies](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html).

  If you include the `Filter` element in a replication configuration, you must
  also include the `DeleteMarkerReplication` and `Priority` elements. The response
  also returns those elements.

  For information about `GetBucketReplication` errors, see [List of replication-related error
  codes](https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ReplicationErrorCodeList)

  The following operations are related to `GetBucketReplication`:

    *
  [PutBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html)     *
  [DeleteBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketReplication.html)
  """
  def get_bucket_replication(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?replication"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the request payment configuration of a bucket.

  To use this version of the operation, you must be the bucket owner. For more
  information, see [Requester Pays Buckets](https://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html).

  The following operations are related to `GetBucketRequestPayment`:

    *
  [ListObjects](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html)
  """
  def get_bucket_request_payment(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?requestPayment"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the tag set associated with the bucket.

  To use this operation, you must have permission to perform the
  `s3:GetBucketTagging` action. By default, the bucket owner has this permission
  and can grant this permission to others.

  `GetBucketTagging` has the following special error:

    * Error code: `NoSuchTagSet`

      * Description: There is no tag set associated with the
  bucket.

  The following operations are related to `GetBucketTagging`:

    *
  [PutBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html)     *
  [DeleteBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html)
  """
  def get_bucket_tagging(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?tagging"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the versioning state of a bucket.

  To retrieve the versioning state of a bucket, you must be the bucket owner.

  This implementation also returns the MFA Delete status of the versioning state.
  If the MFA Delete status is `enabled`, the bucket owner must use an
  authentication device to change the versioning state of the bucket.

  The following operations are related to `GetBucketVersioning`:

    *
  [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)     *
  [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)

    *
  [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html)
  """
  def get_bucket_versioning(
        %Client{} = client,
        bucket,
        expected_bucket_owner \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?versioning"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the website configuration for a bucket.

  To host website on Amazon S3, you can configure a bucket as website by adding a
  website configuration. For more information about hosting websites, see [Hosting Websites on Amazon
  S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html).

  This GET action requires the `S3:GetBucketWebsite` permission. By default, only
  the bucket owner can read the bucket website configuration. However, bucket
  owners can allow other users to read the website configuration by writing a
  bucket policy granting them the `S3:GetBucketWebsite` permission.

  The following operations are related to `DeleteBucketWebsite`:

    *
  [DeleteBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketWebsite.html)     *
  [PutBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketWebsite.html)
  """
  def get_bucket_website(%Client{} = client, bucket, expected_bucket_owner \\ nil, options \\ []) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}?website"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    query_params = []

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Retrieves objects from Amazon S3.

  To use `GET`, you must have `READ` access to the object. If you grant `READ`
  access to the anonymous user, you can return the object without using an
  authorization header.

  An Amazon S3 bucket has no directory hierarchy such as you would find in a
  typical computer file system. You can, however, create a logical hierarchy by
  using object key names that imply a folder structure. For example, instead of
  naming an object `sample.jpg`, you can name it
  `photos/2006/February/sample.jpg`.

  To get an object from such a logical hierarchy, specify the full key name for
  the object in the `GET` operation. For a virtual hosted-style request example,
  if you have the object `photos/2006/February/sample.jpg`, specify the resource
  as `/photos/2006/February/sample.jpg`. For a path-style request example, if you
  have the object `photos/2006/February/sample.jpg` in the bucket named
  `examplebucket`, specify the resource as
  `/examplebucket/photos/2006/February/sample.jpg`. For more information about
  request types, see [HTTP Host Header Bucket Specification](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html#VirtualHostingSpecifyBucket).

  For more information about returning the ACL of an object, see
  [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html).  If the object you are retrieving is stored in the S3 Glacier or S3 Glacier Deep
  Archive storage class, or S3 Intelligent-Tiering Archive or S3
  Intelligent-Tiering Deep Archive tiers, before you can retrieve the object you
  must first restore a copy using
  [RestoreObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html).
  Otherwise, this action returns an `InvalidObjectStateError` error. For
  information about restoring archived objects, see [Restoring Archived Objects](https://docs.aws.amazon.com/AmazonS3/latest/dev/restoring-objects.html).

  Encryption request headers, like `x-amz-server-side-encryption`, should not be
  sent for GET requests if your object uses server-side encryption with KMS keys
  (SSE-KMS) or server-side encryption with Amazon S3–managed encryption keys
  (SSE-S3). If your object does use these types of keys, you’ll get an HTTP 400
  BadRequest error.

  If you encrypt an object by using server-side encryption with customer-provided
  encryption keys (SSE-C) when you store the object in Amazon S3, then when you
  GET the object, you must use the following headers:

    * x-amz-server-side-encryption-customer-algorithm

    * x-amz-server-side-encryption-customer-key

    * x-amz-server-side-encryption-customer-key-MD5

  For more information about SSE-C, see [Server-Side Encryption (Using Customer-Provided Encryption
  Keys)](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html).

  Assuming you have the relevant permission to read object tags, the response also
  returns the `x-amz-tagging-count` header that provides the count of number of
  tags associated with the object. You can use
  [GetObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html) to retrieve the tag set associated with an object.

  ## Permissions

  You need the relevant read object (or version) permission for this operation.
  For more information, see [Specifying Permissions in a
  Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html).
  If the object you request does not exist, the error Amazon S3 returns depends on
  whether you also have the `s3:ListBucket` permission.

    * If you have the `s3:ListBucket` permission on the bucket, Amazon
  S3 will return an HTTP status code 404 ("no such key") error.

    * If you don’t have the `s3:ListBucket` permission, Amazon S3 will
  return an HTTP status code 403 ("access denied") error.

  ## Versioning

  By default, the GET action returns the current version of an object. To return a
  different version, use the `versionId` subresource.

     If you supply a `versionId`, you need the `s3:GetObjectVersion`
  permission to access a specific version of an object. If you request a specific
  version, you do not need to have the `s3:GetObject` permission.

     If the current version of the object is a delete marker, Amazon S3
  behaves as if the object was deleted and includes `x-amz-delete-marker: true` in
  the response.

  For more information about versioning, see
  [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html).  ## Overriding Response Header Values

  There are times when you want to override certain response header values in a
  GET response. For example, you might override the `Content-Disposition` response
  header value in your GET request.

  You can override values for a set of response headers using the following query
  parameters. These response header values are sent only on a successful request,
  that is, when status code 200 OK is returned. The set of headers you can
  override using these parameters is a subset of the headers that Amazon S3
  accepts when you create an object. The response headers that you can override
  for the GET response are `Content-Type`, `Content-Language`, `Expires`,
  `Cache-Control`, `Content-Disposition`, and `Content-Encoding`. To override
  these header values in the GET response, you use the following request
  parameters.

  You must sign the request, either using an Authorization header or a presigned
  URL, when using these parameters. They cannot be used with an unsigned
  (anonymous) request.

    * `response-content-type`

    * `response-content-language`

    * `response-expires`

    * `response-cache-control`

    * `response-content-disposition`

    * `response-content-encoding`

  ## Additional Considerations about Request Headers

  If both of the `If-Match` and `If-Unmodified-Since` headers are present in the
  request as follows: `If-Match` condition evaluates to `true`, and;
  `If-Unmodified-Since` condition evaluates to `false`; then, S3 returns 200 OK
  and the data requested.

  If both of the `If-None-Match` and `If-Modified-Since` headers are present in
  the request as follows:` If-None-Match` condition evaluates to `false`, and;
  `If-Modified-Since` condition evaluates to `true`; then, S3 returns 304 Not
  Modified response code.

  For more information about conditional requests, see [RFC
  7232](https://tools.ietf.org/html/rfc7232).

  The following operations are related to `GetObject`:

    *
  [ListBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html)     *
  [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html)
  """
  def get_object(
        %Client{} = client,
        bucket,
        key,
        part_number \\ nil,
        response_cache_control \\ nil,
        response_content_disposition \\ nil,
        response_content_encoding \\ nil,
        response_content_language \\ nil,
        response_content_type \\ nil,
        response_expires \\ nil,
        version_id \\ nil,
        checksum_mode \\ nil,
        expected_bucket_owner \\ nil,
        if_match \\ nil,
        if_modified_since \\ nil,
        if_none_match \\ nil,
        if_unmodified_since \\ nil,
        range \\ nil,
        request_payer \\ nil,
        sse_customer_algorithm \\ nil,
        sse_customer_key \\ nil,
        sse_customer_key_md5 \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}"
    headers = []

    headers =
      if !is_nil(checksum_mode) do
        [{"x-amz-checksum-mode", checksum_mode} | headers]
      else
        headers
      end

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    headers =
      if !is_nil(if_match) do
        [{"If-Match", if_match} | headers]
      else
        headers
      end

    headers =
      if !is_nil(if_modified_since) do
        [{"If-Modified-Since", if_modified_since} | headers]
      else
        headers
      end

    headers =
      if !is_nil(if_none_match) do
        [{"If-None-Match", if_none_match} | headers]
      else
        headers
      end

    headers =
      if !is_nil(if_unmodified_since) do
        [{"If-Unmodified-Since", if_unmodified_since} | headers]
      else
        headers
      end

    headers =
      if !is_nil(range) do
        [{"Range", range} | headers]
      else
        headers
      end

    headers =
      if !is_nil(request_payer) do
        [{"x-amz-request-payer", request_payer} | headers]
      else
        headers
      end

    headers =
      if !is_nil(sse_customer_algorithm) do
        [{"x-amz-server-side-encryption-customer-algorithm", sse_customer_algorithm} | headers]
      else
        headers
      end

    headers =
      if !is_nil(sse_customer_key) do
        [{"x-amz-server-side-encryption-customer-key", sse_customer_key} | headers]
      else
        headers
      end

    headers =
      if !is_nil(sse_customer_key_md5) do
        [{"x-amz-server-side-encryption-customer-key-MD5", sse_customer_key_md5} | headers]
      else
        headers
      end

    query_params = []

    query_params =
      if !is_nil(version_id) do
        [{"versionId", version_id} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(response_expires) do
        [{"response-expires", response_expires} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(response_content_type) do
        [{"response-content-type", response_content_type} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(response_content_language) do
        [{"response-content-language", response_content_language} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(response_content_encoding) do
        [{"response-content-encoding", response_content_encoding} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(response_content_disposition) do
        [{"response-content-disposition", response_content_disposition} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(response_cache_control) do
        [{"response-cache-control", response_cache_control} | query_params]
      else
        query_params
      end

    query_params =
      if !is_nil(part_number) do
        [{"partNumber", part_number} | query_params]
      else
        query_params
      end

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [
          {"x-amz-checksum-crc32c", "ChecksumCRC32C"},
          {"x-amz-delete-marker", "DeleteMarker"},
          {"x-amz-object-lock-retain-until-date", "ObjectLockRetainUntilDate"},
          {"x-amz-restore", "Restore"},
          {"x-amz-server-side-encryption-bucket-key-enabled", "BucketKeyEnabled"},
          {"Content-Type", "ContentType"},
          {"x-amz-server-side-encryption-customer-key-MD5", "SSECustomerKeyMD5"},
          {"x-amz-object-lock-legal-hold", "ObjectLockLegalHoldStatus"},
          {"x-amz-version-id", "VersionId"},
          {"accept-ranges", "AcceptRanges"},
          {"x-amz-website-redirect-location", "WebsiteRedirectLocation"},
          {"Content-Language", "ContentLanguage"},
          {"x-amz-server-side-encryption-customer-algorithm", "SSECustomerAlgorithm"},
          {"Content-Encoding", "ContentEncoding"},
          {"x-amz-checksum-sha256", "ChecksumSHA256"},
          {"ETag", "ETag"},
          {"Last-Modified", "LastModified"},
          {"Content-Range", "ContentRange"},
          {"Expires", "Expires"},
          {"x-amz-tagging-count", "TagCount"},
          {"x-amz-expiration", "Expiration"},
          {"x-amz-replication-status", "ReplicationStatus"},
          {"Cache-Control", "CacheControl"},
          {"x-amz-storage-class", "StorageClass"},
          {"x-amz-missing-meta", "MissingMeta"},
          {"Content-Length", "ContentLength"},
          {"x-amz-object-lock-mode", "ObjectLockMode"},
          {"Content-Disposition", "ContentDisposition"},
          {"x-amz-request-charged", "RequestCharged"},
          {"x-amz-server-side-encryption", "ServerSideEncryption"},
          {"x-amz-mp-parts-count", "PartsCount"},
          {"x-amz-server-side-encryption-aws-kms-key-id", "SSEKMSKeyId"},
          {"x-amz-checksum-crc32", "ChecksumCRC32"},
          {"x-amz-checksum-sha1", "ChecksumSHA1"}
        ]
      )

    options =
      Keyword.put(
        options,
        :receive_body_as_binary?,
        true
      )

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Returns the access control list (ACL) of an object.

  To use this operation, you must have `s3:GetObjectAcl` permissions or `READ_ACP`
  access to the object. For more information, see [Mapping of ACL permissions and access policy
  permissions](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#acl-access-policy-permission-mapping)
  in the *Amazon S3 User Guide*

  This action is not supported by Amazon S3 on Outposts.

  ## Versioning

  By default, GET returns ACL information about the current version of an object.
  To return ACL information about a different version, use the versionId
  subresource.

  If your bucket uses the bucket owner enforced setting for S3 Object Ownership,
  requests to read ACLs are still supported and return the
  `bucket-owner-full-control` ACL with the owner being the account that created
  the bucket. For more information, see [ Controlling object ownership and disabling
  ACLs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html)
  in the *Amazon S3 User Guide*.

  The following operations are related to `GetObjectAcl`:

    *
  [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)     *
  [GetObjectAttributes](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html)

    *
  [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html)     *
  [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
  """
  def get_object_acl(
        %Client{} = client,
        bucket,
        key,
        version_id \\ nil,
        expected_bucket_owner \\ nil,
        request_payer \\ nil,
        options \\ []
      ) do
    url_path = "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}?acl"
    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    headers =
      if !is_nil(request_payer) do
        [{"x-amz-request-payer", request_payer} | headers]
      else
        headers
      end

    query_params = []

    query_params =
      if !is_nil(version_id) do
        [{"versionId", version_id} | query_params]
      else
        query_params
      end

    options =
      Keyword.put(
        options,
        :response_header_parameters,
        [{"x-amz-request-charged", "RequestCharged"}]
      )

    meta = metadata()

    Request.request_rest(client, meta, :get, url_path, query_params, headers, nil, options, nil)
  end

  @doc """
  Retrieves all the metadata from an object without returning the object itself.

  This action is useful if you're interested only in an object's metadata. To use
  `GetObjectAttributes`, you must have READ access to the object.

  `GetObjectAttributes` combines the functionality of `GetObjectAcl`,
  `GetObjectLegalHold`, `GetObjectLockConfiguration`, `GetObjectRetention`,
  `GetObjectTagging`, `HeadObject`, and `ListParts`. All of the data returned with
  each of those individual calls can be returned with a single call to
  `GetObjectAttributes`.

  If you encrypt an object by using server-side encryption with customer-provided
  encryption keys (SSE-C) when you store the object in Amazon S3, then when you
  retrieve the metadata from the object, you must use the following headers:

    * `x-amz-server-side-encryption-customer-algorithm`

    * `x-amz-server-side-encryption-customer-key`

    * `x-amz-server-side-encryption-customer-key-MD5`

  For more information about SSE-C, see [Server-Side Encryption (Using Customer-Provided Encryption
  Keys)](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html)
  in the *Amazon S3 User Guide*.

     Encryption request headers, such as `x-amz-server-side-encryption`,
  should not be sent for GET requests if your object uses server-side encryption
  with Amazon Web Services KMS keys stored in Amazon Web Services Key Management
  Service (SSE-KMS) or server-side encryption with Amazon S3 managed encryption
  keys (SSE-S3). If your object does use these types of keys, you'll get an HTTP
  `400 Bad Request` error.

     The last modified property in this case is the creation date of the
  object.

  Consider the following when using request headers:

    * If both of the `If-Match` and `If-Unmodified-Since` headers are
  present in the request as follows, then Amazon S3 returns the HTTP status code
  `200 OK` and the data requested:

      * `If-Match` condition evaluates to `true`.

      * `If-Unmodified-Since` condition evaluates to `false`.

    * If both of the `If-None-Match` and `If-Modified-Since` headers are
  present in the request as follows, then Amazon S3 returns the HTTP status code
  `304 Not Modified`:

      * `If-None-Match` condition evaluates to `false`.

      * `If-Modified-Since` condition evaluates to `true`.

  For more information about conditional requests, see [RFC 7232](https://tools.ietf.org/html/rfc7232).

  ## Permissions

  The permissions that you need to use this operation depend on whether the bucket
  is versioned. If the bucket is versioned, you need both the
  `s3:GetObjectVersion` and `s3:GetObjectVersionAttributes` permissions for this
  operation. If the bucket is not versioned, you need the `s3:GetObject` and
  `s3:GetObjectAttributes` permissions. For more information, see [Specifying Permissions in a
  Policy](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html)
  in the *Amazon S3 User Guide*. If the object that you request does not exist,
  the error Amazon S3 returns depends on whether you also have the `s3:ListBucket`
  permission.

    * If you have the `s3:ListBucket` permission on the bucket, Amazon
  S3 returns an HTTP status code `404 Not Found` ("no such key") error.

    * If you don't have the `s3:ListBucket` permission, Amazon S3
  returns an HTTP status code `403 Forbidden` ("access denied") error.

  The following actions are related to `GetObjectAttributes`:

    *
  [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)     *
  [GetObjectAcl](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAcl.html)

    *
  [GetObjectLegalHold](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLegalHold.html)     *
  [GetObjectLockConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLockConfiguration.html)

    *
  [GetObjectRetention](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectRetention.html)     *
  [GetObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html)

    *
  [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)     *
  [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)
  """
  def get_object_attributes(
        %Client{} = client,
        bucket,
        key,
        version_id \\ nil,
        expected_bucket_owner \\ nil,
        max_parts \\ nil,
        object_attributes,
        part_number_marker \\ nil,
        request_payer \\ nil,
        sse_customer_algorithm \\ nil,
        sse_customer_key \\ nil,
        sse_customer_key_md5 \\ nil,
        options \\ []
      ) do
    url_path =
      "/#{AWS.Util.encode_uri(bucket)}/#{AWS.Util.encode_multi_segment_uri(key)}?attributes"

    headers = []

    headers =
      if !is_nil(expected_bucket_owner) do
        [{"x-amz-expected-bucket-owner", expected_bucket_owner} | headers]
      else
        headers
      end

    headers =
      if !is_nil(max_parts) do
        [{"x-amz-max-parts", max_parts} | headers]
      else
        headers
      end

    headers =
      if !is_nil(object_attributes) do
        [{"x-amz-object-attributes", object_attributes} | headers]
      else
        headers
      end

    headers<