moto icon indicating copy to clipboard operation
moto copied to clipboard

S3 HeadObject does not support range header

Open tekumara opened this issue 1 year ago • 1 comments

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

tekumara avatar Aug 28 '24 10:08 tekumara

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:

bblommers avatar Aug 29 '24 18:08 bblommers