moto
moto copied to clipboard
S3 HeadObject does not support range header
The real S3 API supports the range header on a HeadObject request, even though the response body is empty. Some clients, like TransferManager used by tensorflow-io, send HeadObject requests with a range header to determine the content length up front. But when used with moto server they will receive a 416.
MRE
Run moto server on port 3000:
moto_server -p3000
Create bucket, object and head object request:
import boto3
import io
# Create a mock S3 client
s3 = boto3.client('s3',
endpoint_url='http://localhost:3000', aws_access_key_id="foo", aws_secret_access_key="bar")
# Create a bucket
bucket_name = 'my-tfrecord-bucket'
s3.create_bucket(Bucket=bucket_name)
## Put object
response = s3.put_object(
Bucket='my-tfrecord-bucket',
Key='hello',
Body='world'
)
## Head object request with range
s3.head_object(
Bucket='my-tfrecord-bucket',
Key='hello',
Range='bytes=0-9'
)
Errors with:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "../.venv/lib/python3.11/site-packages/botocore/client.py", line 565, in _api_call
return self._make_api_call(operation_name, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "../.venv/lib/python3.11/site-packages/botocore/client.py", line 1017, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (416) when calling the HeadObject operation: Requested Range Not Satisfiable
moto 5.0.13
Hi @tekumara, thanks for raising this! Moto supports this for GET-requests, but made an explicit assumption that the request returns something - causing it to fail for (HEAD) requests without a body.
I've opened a PR to also make this work for HEAD requests. :+1: