boro2g
boro2g

Reputation: 524

Why is AWS Gateway setting the wrong content length for an image streamed from S3?

Using the out the box Serverless template for C# .Net Core 2.0, I've created an S3 bucket that contains an image - I want to display this in a browser.

Running the webapi locally I can view the image fine and the content-length header isn't even included. When accessing via https://apidemo.boro2g.co.uk/media/mirrored-faces.jpg the content-length is getting changed to be bigger than it should. The original image is roughly 300kb but out of the API gateway its roughly 400kb.

I want to use the proxy to apply some custom security over the images so don't want them to be public, for testing you can see the original at https://s3-eu-west-1.amazonaws.com/boro2g-photogallery/mirrored-faces.jpg

I've tried adding the binary media types as well within the API but these don't seem to have any effect.

The code to 'get' the image is pretty simple:

[HttpGet("{key}")]
    public async Task Get(string key)
    {
        try
        {
            var getResponse = await S3Client.GetObjectAsync(new GetObjectRequest
            {
                BucketName = BucketName,
                Key = key
            });

            Response.ContentType = getResponse.Headers.ContentType;

            getResponse.ResponseStream.CopyTo(Response.Body);
        }
        catch (AmazonS3Exception e)
        {
            Response.StatusCode = (int)e.StatusCode;
            var writer = new StreamWriter(Response.Body);
            writer.Write(e.Message);
        }
    }

Why would the API be updating the content-length incorrectly?

FYI static txt files load without problem: https://apidemo.boro2g.co.uk/media/test.txt

Upvotes: 2

Views: 1844

Answers (3)

AamirR
AamirR

Reputation: 12218

Why is AWS Gateway setting the wrong content length for an image streamed from S3?

Your API Gateway is not rendering the binary data properly, its assuming the data is string in a different encoding such as base64, following did fix the issue.

API Settings > Binary Media Types */*

API Method Response, Add HTTP Status 200, and set desired Content-Type header

check screenshot

I also had to apply following patch for the response body to be converted to binary.

aws apigateway update-integration-response \
    --profile AWS_PROFILE_NAME \
    --rest-api-id API_ID \
    --resource-id RESOURCE_ID \
    --region AWS_REGION \
    --http-method GET \
    --status-code 200 \
    --patch-operations '[{"op" : "replace", "path" : "/contentHandling", "value" : "CONVERT_TO_BINARY"}]'

Upvotes: 0

Admon Sasson
Admon Sasson

Reputation: 229

  • In the api gateway settings, add */* (or the exact content types) to the Binary Media Type
  • Click the "Deploy API" button (didn't work without it)
  • I had to wait couple of minutes

Upvotes: 1

boro2g
boro2g

Reputation: 524

In the end the solution I found to work was:

  1. In the settings for your api gateway, add the Binary Media Type: */*
  2. On the {proxy+} method ‘Method Response’ add a 200 response header and add a header Content-Type. Finally publish your api

The second step here may not be necessary but I found the / didn’t kick in until I made the change.

Upvotes: 4

Related Questions