AWS API Gateway base64Decode produces garbled binary?
To anyone else having problems with this: I was also banging my head against the wall trying to retrieve a binary image over API Gateway proxy integration from lambda, but then I noticed that it says right there in the Binary Support section of Lambda Console:
API Gateway will look at the Content-Type and Accept HTTP headers to decide how to handle the body.
So I added Accept: image/png
to the request headers and it worked. Oh the joy, and joyness!
No need to manually change content handling to CONVERT_TO_BINARY or muck about with the cli. Of course this rules out using, for example, <img src=
directly (can't set headers).
So, in order to get a binary file over API Gateway from lambda with proxy integration:
- List all supported binary content types in the lambda console (and deploy)
- The request Accept header must include the Content-Type header returned from the lambda expression
- The returned body must be base64 encoded
- The result object must also have the
isBase64Encoded
property set totrue
Code:
callback(null, {
statusCode: 200,
headers: { 'Content-Type': 'image/png' },
body: buffer.toString('base64'),
isBase64Encoded: true
}
It looks like this was a known issue previously: https://forums.aws.amazon.com/thread.jspa?messageID=668306򣊒
But it should be possible now that they've added support for binary data: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings.html
It looks like this is the bit we need: "Set the contentHandling property of the IntegrationResponse resource to CONVERT_TO_BINARY to have the response payload converted from a Base64-encoded string to its binary blob". Then we shouldn't need the base64Decode()
function.
Working on a test now to see if this works.
EDIT: I was finally able to get this working. You can see the binary image here: https://chtskiuz10.execute-api.us-east-1.amazonaws.com/prod/rest/image
Here's my Lambda function that returns the base64 encoded PNG as a string: https://gist.github.com/davemaple/73ce3c2c69d5310331395a0210069263
I updated the method response as follows:
I updated the integration response to include a hard-coded image/png header:
The last step was tricky: setting the contentHandling
property to "CONVERT_TO_BINARY". I couldn't figure out how to do in the AWS console. I had to use the CLI API to accomplish this:
aws apigateway update-integration-response \
--profile davemaple \
--rest-api-id chtskiuzxx \
--resource-id ki1lxx \
--http-method GET \
--status-code 200 \
--patch-operations '[{"op" : "replace", "path" : "/contentHandling", "value" : "CONVERT_TO_BINARY"}]'
I hope this helps.
Check out this answer. It helped me with exposing PDF file for download through GET request without any additional headers.