allencoded
allencoded

Reputation: 7285

Using lambda to serve bucket image resources through API Gateway results in a broken image

I am using AWS Api Gateway, Lambda, and S3.

My goal is to hit the gateway and serve and display an image from my S3 bucket in the browser. Currently I am able to successfully fetch the image from the appropriate bucket using the AWS SDK in my lambda no problem. I then send it over the wire as and the response is 200 and I can see all the appropriate headers. However the image is broken.

Here is the code in my lambda:

const AWS = require('aws-sdk');

const s3 = new AWS.S3();

exports.handler = async (event) => {
  const bucketParams = {
    Bucket: 'my-bucket',
    Key: 'build/cat.jpg',
  };
    
    const bucket = await s3.getObject(bucketParams).promise();
    
    const response = {
        statusCode: 200,
        body: Buffer.from(bucket.Body).toString(),
        headers: {
            'Accept-Ranges': 'bytes',
            'Content-Length': bucket.ContentLength,
            'Content-Type': bucket.ContentType,
            'Last-Modified': bucket.LastModified,
            'ETag': bucket.Etag,
        }
    };
    
    return response;
};

The response is a 200, everything works but my image appears to be broken in the browser. Here is a uri of the example https://3bn2t9npbd.execute-api.us-east-1.amazonaws.com/dev/cat.jpg

As a side note I serve more than just images through this code the example above though is just a single image.

Upvotes: 4

Views: 706

Answers (1)

allencoded
allencoded

Reputation: 7285

I was able to figure out the solution to my problem. Thanks to jarmod for pointing me in the right direction. I first had to enable Binary Media Types for all content in my AWS Gateway Settings pictured below.

enter image description here

After that I changed the lambda code to response to be:

const bucket = await s3.getObject(bucketParams).promise();
    
const response = {
  statusCode: 200,
  body: Buffer.from(bucket.Body).toString("base64"),
  headers: {
    'Accept-Ranges': 'bytes',
    'Content-Length': bucket.ContentLength,
    'Content-Type': bucket.ContentType,
    'Last-Modified': bucket.LastModified,
  },
  isBase64Encoded: true,
};
    
return response;

Upvotes: 3

Related Questions