AWS API Gateway base64Decode produces garbled binary?

僤鯓⒐⒋嵵緔 提交于 2019-11-26 08:13:32

问题


I\'m trying to return a 1px gif from an AWS API Gateway method.

Since binary data is now supported, I return an image/gif using the following \'Integration Response\' mapping:

$util.base64Decode(\"R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\")

However, when I look at this in Chrome, I see the following binary being returned:

Instead of:

Could anyone help me understand why this is garbled and the wrong length? Or what I could do to return the correct binary? Is there some other what I could always return this 1px gif without using the base64Decode function?

Many thanks in advance, this has being causing me a lot of pain!

EDIT

This one gets stranger. It looks like the issue is not with base64Decode, but with the general handling of binary. I added a Lambda backend (previously I was using Firehose) following this blog post and this Stack Overflow question. I set images as binaryMediaType as per this documentation page.

This has let me pass the following image/bmp pixel from Lambda through the Gateway API, and it works correctly:

exports.handler = function(event, context) {

  var imageHex = \"\\x42\\x4d\\x3c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x36\\x00\\x00\\x00\\x28\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x27\\x00\\x00\\x00\\x27\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\";
  context.done(null, { \"body\":imageHex });

};

However the following images representing an image/png or a image/gif get garbled when passed through:

exports.handler = function(event, context) {

//var imageHex = \"\\x47\\x49\\x46\\x38\\x39\\x61\\x01\\x00\\x01\\x00\\x80\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\x21\\xf9\\x04\\x01\\x00\\x00\\x00\\x00\\x2c\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x01\\x44\\x00\\x3b\";
//var imageHex = \"\\x47\\x49\\x46\\x38\\x39\\x61\\x01\\x00\\x01\\x00\\x80\\x00\\x00\\xff\\xff\\xff\\x00\\x00\\x00\\x21\\xf9\\x04\\x01\\x00\\x00\\x00\\x00\\x2c\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x02\\x44\\x01\\x00\\x3b\";
  var imageHex = \"\\x47\\x49\\x46\\x38\\x39\\x61\\x01\\x00\\x01\\x00\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x21\\xf9\\x04\\x01\\x00\\x00\\x00\\x00\\x2c\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x02\\x44\\x01\\x00\\x3b\\x0a\"
  context.done(null, { \"body\":imageHex });

};

This seems to be the same issue as another Stack Overflow question, but I was hoping this would be fixed with the Gateway API binary support. Unfortunately image/bmp doesn\'t work for my use case as it can\'t be transparent...

In case it helps anyone, this has been a good tool for converting between base64 and hex.


回答1:


It looks like this was a known issue previously: https://forums.aws.amazon.com/thread.jspa?messageID=668306&#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.




回答2:


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 to true

Code:

callback(null, {
    statusCode: 200,
    headers: { 'Content-Type': 'image/png' },
    body: buffer.toString('base64'),
    isBase64Encoded: true
}



回答3:


Check out this answer. It helped me with exposing PDF file for download through GET request without any additional headers.



来源:https://stackoverflow.com/questions/41429551/aws-api-gateway-base64decode-produces-garbled-binary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!