1
votes

I'm using AWS API Gateway integrated with Lambda.

Note: I am NOT using Lambda Proxy.

I need to return a binary response from API Gateway. I have successfully set this up as follows:

  1. Encoded my binary data as base64 UTF-8 string and returning ONLY that from my lambda function return "base64 encoded binary data"
  2. Enabled CONVERT_TO_BINARY on the API Gateway Integration Response
  3. Mapped the Content-Type header on the API Gateway Method Response to the binary media type of my binary content
  4. Added the media type of my binary content to API Gateway's list of Binary Media Types

The issue is that as well as sending the binary data (which I can do successfully from the above steps), I need to include a x-my-header custom header in the API Response.

I know how to set-up header mapping in the API Gateway, but the header has to be calculated from database data, and therefore this value needs to also be returned from lambda.

My understanding of lambda integration (remember, I'm not using lambda proxy here) is that API gateway makes a HTTP request to trigger lambda. Lambda then returns a HTTP response to API Gateway, adding the functions output to the body, and also adding internal aws headers to the response.

Now it is possible to map a header to the Method Response using:

integration.response.header.header-name

My question is...

Can I tell lambda to add my custom header to a binary response, when I'm using custom lambda integration (not proxy) ?

Note: IF i was using lambda proxy, I know that the return object looks as below, and then I would be able to send custom headers. But for reasons out of my control, I cant use lambda proxy.

Lambda return object solution IF i was using lambda proxy:

return {
   'body': "base64 encoded binary data",
   'headers': 'x-my-header': 'my-value',
   'isBase64Encoded': True
}

For Lambda Integration (not proxy) I have tried modifying my lambda output...

return {
   "base64-data": "base64 encoded binary data",
   "x-my-header: "some value"
}

And setting up a mapping template in the integration response...

$input.json("$.base64-data")

And setting up a header mapping using...

integration.response.body.x-my-header

But API Gateway returns an error:

Execution failed due to configuration error: Unable to transform response

I believe this error occurs because there cannot be a mapping template when you have CONVERT_TO_BINARY enable. From AWS docs:

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.

1

1 Answers

0
votes

I realize this is an old question, but I ran into a similar header mapping issue recently, even though I'm not using binary data.

To my mind the return from Lambda could look like this

{
  "base64-data": "base64 encoded binary data",
   "x-my-header: "some value"
}

Based on that Lambda Response, you could apply the following mapping (which I modified based on an AWS example)

$input.json("$.base64-data")
#set($context.responseOverride.header.x-my-header = "$input.json('$.x-my-header')")

$input.json("$") references your response and $.[key] is the right way to reference your sub-keys.

You also have to preconfigure your header "x-my-header" in your method response.

In the integration Response the header mapping can just be an empty value - e.g.

""

The real value will be provided by the override ($context.responseOverride.header) which is set by the mapping template.