gene_wood
gene_wood

Reputation: 2073

How does the IfMatch argument for the AWS boto3 get_object call work?

The boto3 s3 get_object function documentation (which is autogenerated from AWS service definition files) describes the IfMatch argument as

Return the object only if its entity tag (ETag) is the same as the one specified, otherwise return a 412 (precondition failed).

However when I try to use the IfMatch argument I'm unable to get S3 to respond either with a non-200 HTTP status code or by throwing an exception.

This example code

import boto3
import hashlib
import json

BUCKET = 'your-bucket-name-goes-here'
data = {'foo': 'bar', 'baz': 'buz'}
payload = json.dumps(data, sort_keys=True, indent=4).encode('UTF-8')
etag = hashlib.md5(payload).hexdigest()
print("Locally computed etag : {}".format(etag))
client = boto3.client('s3')
response = client.put_object(
    Body=payload,
    Bucket=BUCKET,
    ContentType='application/json',
    Key='/test.json')
etag_with_quotes = response['ETag']
print("Etag returned from put_object: {}".format(etag_with_quotes))

response = client.get_object(
  Bucket=BUCKET,
  Key='/test.json',
  IfMatch=etag
)
print("Etag returned from get_object: {}".format(response['ETag']))
print("HTTP status code : {}".format(response['ResponseMetadata']['HTTPStatusCode']))

response = client.get_object(
  Bucket=BUCKET,
  Key='/test.json',
  IfMatch=etag_with_quotes
)
print("Etag returned from get_object: {}".format(response['ETag']))
print("HTTP status code : {}".format(response['ResponseMetadata']['HTTPStatusCode']))

produces this output

Locally computed etag : d14e36174d57c305bd9d7c171e669ac8
Etag returned from put_object: "d14e36174d57c305bd9d7c171e669ac8"
Etag returned from get_object: "d14e36174d57c305bd9d7c171e669ac8"
HTTP status code : 200
Etag returned from get_object: "d14e36174d57c305bd9d7c171e669ac8"
HTTP status code : 200

How is one supposed to use the IfMatch argument to avoid downloading a file if the local copy is the same?

Upvotes: 1

Views: 1702

Answers (1)

Michael - sqlbot
Michael - sqlbot

Reputation: 179414

IfMatch downloads the object if the ETag matches. To download only if different, use IfNoneMatch.


Note also that this only works for objects not uploaded using multipart uploads. Multpart uploads use a different ETag algorithm containing a hex md5 hash of the binary (not hex) md5 hashes of the individual parts, then a -, and then the number of parts. You can successfully calculate these yourself, but it's more complicated.

Upvotes: 3

Related Questions