4
votes

I have a lambda that needs to return a binary object and some http headers (e.g. content-type) through an api gateway (using lambda integration) OR redirect to another URL. In the binary support examples (e.g. https://aws.amazon.com/blogs/compute/binary-support-for-api-integrations-with-amazon-api-gateway/) the lambda only returns the (base64 of the) binary object (the image). In my case, I also need to return a status code and http headers (or something equivalent). I struggle with how I can make this work with binary support in api gateway.

The lambda returns a json on this form:

{
  "statusCode": 200,
  "headers": {
    "content-type": "image/jpeg"
  },
  "body": "/9j/4AAQS...gLDAoKCAwZK",
  "isBase64Encoded": true
}

In the integration response I add body mappings for image/jpeg (etc) of the form:

$input.json('$.body')

And header mapping for 'content-type' like so:

integration.response.body.headers['content-type']

I've tried many variations of the above, but the result is consistently

Execution failed due to configuration error: Unable to transform response 

How do I transform the json from the lambda into a form that can be converted to binary by the api gateway, with http headers and all? Can I get more debug logging out of the api gateway to show more specific what it is unhappy with?

Is there perhaps a way to get more debug logging out of the api gateway?

3
Did you get this working? I have the same challenge...Michael Wiles
No. Sorry. Instead I returned a redirect to another lambda that only returned binary objects. So, several lambdas. Clumsy, but works-simon
I did get this working. Works great in fact. As long as you configure the resource as a proxy resource and ensure that your accept mime type matches the Binary Media Types setting in Settings for your API (in api gateway).Michael Wiles

3 Answers

1
votes

I recently got this working after facing a similar problem.

In my case, I was missing two things:

First, I needed to change the list of types AWS will send to the upstream in the "Accept" header"

"x-amazon-apigateway-binary-media-types" : [
  "image/jpeg"
]

Secondly, I needed to set the Integration Response to "Convert to binary (if needed)":

"contentHandling": "CONVERT_TO_BINARY"

See this answer for the details, and sample config.

I also found that I wasn't being patient enough. Whenever I deployed the API, I was checking immediately, instead of waiting a few minutes for the changes to propagate.

1
votes

I tired returning binary data with base64 encoding, but I couldn't manage to return it from Lambda function through API Gateway.

Therefore, I decided to redirect the URL. I changed the Method Response to 302 and added "Location" Response header. I also deleted response code 200 from Integration Response, selected 302 as response code and mapped integration.response.body.location value with Location header. My Lambda code returned location of redirect URL in this format:

{"location":"www.google.com/"}

Hope this helps.

0
votes

I've been struggling to do the same for days, but couldn't find any documentation to back up that it's possible, instead I found this https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-workflow.html

When converting a text payload to a binary blob, API Gateway assumes that the > text data is a Base64-encoded string and outputs the binary data as a Base64-decoded blob. If the conversion fails, it returns a 500 response indicating an API configuration error. You do not provide a mapping template for such a conversion, although you must enable the passthrough behaviors on the API.

When converting a binary payload to a text string, API Gateway always applies > a Base64 encoding on the binary data. You can define a mapping template for such a payload, but can only access the Base64-encoded string in the mapping template through $input.body, as shown in the following excerpt of an example > mapping template.

which sounds to me that mapping like this is only possible the other way around; what I ended up doing is that just return Base64Encoded binary string and hard code the content-type and cache- control in header mapping; for the complete implementation see my blog post https://mesfinmoges.com/dynamic-image-resizing-using-amazon-s3-aws-lambda-mazon-api-gateway-amazon-cloudfront/