# Use Conditional Requests

Conditional requests provide a way to control whether an action should be executed, based on certain metadata checks associated with an object. Here are some common parameters used for conditional requests:

- **If-Match / If-None-Match**:  
  These parameters compare the object's ETag value before allowing an operation.  
  - *`If-Match`* allows the operation only if the object's ETag matches the given value.  
  - *`If-None-Match`* allows the operation only if the object's ETag does **not** match the given value.  
  - Both parameters also support the wildcard (`*`), which applies the condition to any ETag.

- **If-Modified-Since / If-Unmodified-Since**:  
  These parameters compare the object's last modified date or creation date before proceeding.  
  - *`If-Modified-Since`* allows the operation only if the object has been modified after the specified date.  
  - *`If-Unmodified-Since`* allows the operation only if the object has **not** been modified after the specified date.

- **If-Match-Size / If-Match-Last-Modified-Time**:  
  These are typically used with DeleteObject operations to check the object’s size or last modified time before deletion.

Conditional request logic can also be enforced at the bucket level through bucket policies. For example, you can configure a policy to prevent accidental data overwrites. For detailed guidance, see 
[Bucket policy How-To]({{< ref "product/storage/object-storage/how-to/bucketpolicy/#example-policies" >}}).

**Use cases for conditional requests include:**  
- Preventing conflicts during concurrent object updates  
- Saving bandwidth by avoiding unnecessary data transfers  
- Enabling advanced architectural patterns and workflows on top of SOS


## Requirements

These parameters are generally available, and need only support from the client (eg: AWS S3 cli, Java SDK, etc).
In case of multiple conditional parameters for a single request, SOS follows [RFC7232](https://datatracker.ietf.org/doc/html/rfc7232) as closely as possible.


## Operations

All examples are assuming you are using the AWS S3 cli, however most S3 clients should have support for conditional requests.
Date parameters are formatted as defined by RFC3339 or RFC822:

- `2025-06-09T15:40:42+00:00`
- `Tue, 05 Aug 2025 11:32:21 +0000`

### get-object

Conditional get requests can be useful when the client may expect an existing object to be in place, and may want to save
bandwidth if the client has a local copy.

When retrieving an object, the following parameters can be specified:
- `--if-match <ETag>` gets the object if the `ETag` matches the object `ETag`
- `--if-none-match <ETag>` gets the object if the `ETag` does not match the object `ETag`
- `--if-modified-since <Timestamp>` gets the object if the object `LastModified` is equal or after the `Timestamp`
- `--if-unmodified-since <Timestamp>` gets the object if the object `LastModified` is before the `Timestamp`


### put-object

Conditional put requests can be useful in a high concurrency scenario, where multiple clients can
try to upload a given object but only one should succeed.

When uploading an object, the following parameters can be specified:
- `--if-match <ETag>` puts the object if the `ETag` matches the object `ETag`
- `--if-none-match <ETag>` puts the object if the `ETag` does not match the object `ETag`


### copy-object

Copying an object can accept the following conditional parameters:
- `--copy-source-if-match <ETag>` copy if the source object `ETag` matches the `ETag`
- `--copy-source-if-none-match <ETag>` copy if the source object `ETag` does not match the `ETag`
- `--copy-source-if-modified-since <Timestamp>` copy if the source object `LastModified` is equal or after the `Timestamp`
- `--copy-source-if-unmodified-since <Timestamp>` copy if the source object `LastModified` is before the `Timestamp`

All the parameters refer to the **source** object attributes, and are similar to `get-object` parameters.


### delete-object

Conditional deletes can supply the following parameters:
- `--if-match <ETag>` object will be deleted if its `ETag` matches the supplied `ETag`
- `--if-match-last-modified-time <Timestamp>` object will be deleted if its `LastModified` matches the supplied `Timestamp`
- `--if-match-size <Size>` object will be deleted if its `Size` matches the supplied `Size`

## Example

Below is an example of using the aws cli to conditionally put or get an object.

```shell
# first we put an object
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin 

{
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "VersionId": "1152004336876784859"
}

# we can ensure we overwrite an object given its ETag
# this can be useful for a client that wants to put only if the object hasn't been modified in the meantime
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin --if-match "d41d8cd98f00b204e9800998ecf8427e"
{
    "ETag": "\"323bf3388a58620e50b5b22f550236bb\"",
    "VersionId": "1152004380476574947"
}

# we can also ensure we overwrite anything
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin --if-match "*"
{
    "ETag": "\"3cd3e5bf2f0f53862405768788fd17fb\"",
    "VersionId": "1152004396721115840"
}

# a non-matching ETag will fail
$ aws s3api put-object --bucket my-bucket --key mykey --if-match "<some etag>"

An error occurred (PreconditionFailed) when calling the PutObject operation: Your preconditions were not met.


# but a common case is to only put an object if there isn't one
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin --if-none-match "*"

An error occurred (PreconditionFailed) when calling the PutObject operation: Your preconditions were not met.


##
# assuming we have a copy of the object, a client may only be interested in getting different or newer versions
$ aws s3api get-object --bucket mybuckey --key mykey --if-none-match "<some old etag>" /tmp/mykey
{
    "AcceptRanges": "bytes",
    "LastModified": "2025-08-06T11:59:15+00:00",
    "ContentLength": 0,
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "VersionId": "1152004396721115840",
    "ContentType": "application/binary",
    "Metadata": {}
}

# we can also request an object only if a more recent modification exists
$ aws s3api get-object --bucket mybucket --key mykey --if-modified-since "2025-08-06T11:59:25+00:00" /dev/null

An error occurred (304) when calling the GetObject operation: Not Modified

##
# we can also ask to delete an object only if we match the ETag
# because another client may have updated the object in the meantime
$ aws s3api delete-object --bucket my-bucket --key mykey --if-match "<some old etag>"

An error occurred (PreconditionFailed) when calling the DeleteObject operation: Your preconditions were not met.

# but if the object is still the one the client knows (the etag will match), the object can be safely deleted
$ aws s3api delete-object --bucket my-bucket --key mykey --if-match "d41d8cd98f00b204e9800998ecf8427e"
{
    "DeleteMarker": true,
    "VersionId": "1152006421454263029"
}
```

