AWS SAM Configuration for API Gateway Binary Response / Payloads
Learn how to configure AWS SAM to enable Binary Response such as audio/wav
, application/zip
, image/jpeg
, image/png
etc from AWS Api Gateway with Lambda proxy integration.
Steps
In this walkthrough, I will use application/zip
for example.
1. CloudFormation yaml
To enable Api Gateway Binary Response, you can set x-amazon-apigateway-binary-media-types
in your API’s definition body.
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
DefinitionBody:
swagger: '2.0'
basePath: '/Prod'
schemes:
- 'https'
paths:
/myMethod:
post:
produces:
- "application/json"
responses: {}
x-amazon-apigateway-integration:
uri: # api-gateway-arn using Fn::Join
responses: {}
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
x-amazon-apigateway-binary-media-types:
- "application/zip"
1.1 AWS SAM
Even though AWS SAM provide BinaryMediaTypes
property but as of Aug 2019, there seems to be a bug that will removes the specified binary media type when you deploy updates for your API.
You can check out AWS SAM GitHub issues 553 and 566 for more information and update.
Thus, the following two syntax causes your specified binary media type to be removed in subsequent deployments.
Using Globals Api BinaryMediaTypes property:
Globals:
Api:
BinaryMediaTypes:
- application~1zip
Using Single Api BinaryMediaTypes property:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
BinaryMediaTypes:
- application~1zip
...
1.2 Binary Media Type */*
On the other hand, it works with a wild card binary type: *~1*
. However, requests’ body object will be base64 encoded.
Setting Api BinaryMediaTypes as *~1*
in yaml.
Globals:
Api:
BinaryMediaTypes:
- *~1*
Note that you have to use ~1
instead of /
. API Gateway will convert it to /.
You can check AWS SAM 1.4.0 release log and AWS SAM API properties document for more information.
When BinaryMediaTypes is */*, you need to base64 decode event['body']
to read what it contains.
body = json.loads(base64.b64decode(event['body']))
2. Lambda Response
To pass binary response, you will need to base64 encode it and make it a UTF-8 string. In the response object, you have to include isBase64Encoded: true
and Content-Type
header with value as your payload mime type.
# your binary data is in data variable
byte_data = base64.b64encode(data)
rst_obj['body'] = str(byte_data,'utf-8')
rst_obj['headers']['Content-Type'] = 'application/zip'
Response JSON object
{
"statusCode": 200,
"isBase64Encoded": true,
"body": "//NgxAAd...",
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,X-Api-Key,X-Amz-Security-Token",
"Content-Type": "application/zip"
}
}
Now, git push to deploy the changes.
3. Api Gateway Binary Media Type
After deployment, to verify addition of binary media type, open Api Gateway console and choose your API. Then, select Settings and make sure it has binary media type configured.
4. Http Requests
Your http requests need to include an Accept header with value as your binary media type. For example: Accept: application/zip
.
The following is a http request example using AWS Amplify API object.
apiCall() {
const apiName = 'apiName';
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/zip'
},
responseType: 'blob'
};
return API.post(apiName, '/myApi', config)
.then(response => {
return response;
})
.catch(err => {
console.error('err: ', err);
});
});
}
5. Download Binary
To confirm whether your API returns binary response, it looks like this on Chrome DevTools.
To download your binary data, you can use browser built-in method saveAs
.
this.apiCall()
.then(res => {
saveAs(res, 'myFiles.zip');
});
Conclusion
Setting x-amazon-apigateway-binary-media-types
property or SAM BinaryMediaTypes
enables binary response from API Gateway.
Check out AWS Amplify API, Blob Response Type and Error Handling article to learn how to send requests for binary response on frontend using AWS Amplify.
Support Jun
Thank you for reading! Support Jun
If you are preparing for Software Engineer interviews, I suggest Elements of Programming Interviews in Java for algorithm practice. Good luck!
You can also support me by following me on Medium or Twitter.
Feel free to contact me if you have any questions.
Comments