aws / aws/aws-sam-cli

Bug: BinaryMediaTypes not working with AWS::ApiGateway::RestApi in SAM

Open
#4,593 9 comments 2 reactions 1 assignee Claimed by @qingchm View on GitHub
area/local/start-api stage/bug-repro
Dominant language
Python
Stars
6.7k
Forks
1.2k
Avg merge
1d 10h
Merged PRs (30d)
52

Description

### Description:

I am running my AWS Lambdas locally using SAM and it's sam local start-api -t template.yaml command. Everything works fine apart from one of my Lambdas which is supposed to return an application/pdf binary media type. I have enabled this type of response in the template.yaml I am using to launch SAM.

Here is a snippest of the template.yaml showing this:

```
Resources:
FrontendCertificateapilocalchild7173C752:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: localhost:4000
DomainValidationOptions:
- DomainName: localhost:4000
ValidationDomain: localhost:4000
Tags:
- Key: Name
Value: local/Frontend/Certificate-api-local-child
ValidationMethod: EMAIL
Metadata:
aws:cdk:path: local/Frontend/Certificate-api-local-child/Resource
FrontendApiGatewaylocalfrontendapilocal5C7648A5:
Type: AWS::ApiGateway::RestApi
Properties:
BinaryMediaTypes:
- "*/*"
Description: This service serves the frontend.
Name: Frontend Service
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Resource
```

### Steps to reproduce:

Here is the full template I am using:
```
Resources:
FrontendCertificateapilocalchild7173C752:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: localhost:4000
DomainValidationOptions:
- DomainName: localhost:4000
ValidationDomain: localhost:4000
Tags:
- Key: Name
Value: local/Frontend/Certificate-api-local-child
ValidationMethod: EMAIL
Metadata:
aws:cdk:path: local/Frontend/Certificate-api-local-child/Resource
FrontendApiGatewaylocalfrontendapilocal5C7648A5:
Type: AWS::ApiGateway::RestApi
Properties:
BinaryMediaTypes:
- "*/*"
Description: This service serves the frontend.
Name: Frontend Service
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Resource
FrontendApiGatewaylocalfrontendapilocalCloudWatchRole66A87201:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/CloudWatchRole/Resource
FrontendApiGatewaylocalfrontendapilocalAccount3AC7EEFA:
Type: AWS::ApiGateway::Account
Properties:
CloudWatchRoleArn:
Fn::GetAtt:
- FrontendApiGatewaylocalfrontendapilocalCloudWatchRole66A87201
- Arn
DependsOn:
- FrontendApiGatewaylocalfrontendapilocal5C7648A5
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Account
FrontendApiGatewaylocalfrontendapilocalDeployment86803513d253457674c45cab7d651a56bf762787:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
Description: This service serves the frontend.
DependsOn:
- FrontendApiGatewaylocalfrontendapilocalOPTIONS37358616
- FrontendApiGatewaylocalfrontendapilocalorderOPTIONS93DCA01D
- FrontendApiGatewaylocalfrontendapilocalorderpdfidGET755A64B2
- FrontendApiGatewaylocalfrontendapilocalorderpdfidOPTIONS4050D92E
- FrontendApiGatewaylocalfrontendapilocalorderpdfidC7654574
- FrontendApiGatewaylocalfrontendapilocalorderpdfOPTIONS25C6B290
- FrontendApiGatewaylocalfrontendapilocalorderpdf8ADB696B
- FrontendApiGatewaylocalfrontendapilocalorder190D5B05
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Deployment/Resource
FrontendApiGatewaylocalfrontendapilocalDeploymentStageprodBC56BC1F:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
DeploymentId:
Ref: FrontendApiGatewaylocalfrontendapilocalDeployment86803513d253457674c45cab7d651a56bf762787
StageName: prod
DependsOn:
- FrontendApiGatewaylocalfrontendapilocalAccount3AC7EEFA
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/DeploymentStage.prod/Resource
FrontendApiGatewaylocalfrontendapilocalCustomDomainB4D30972:
Type: AWS::ApiGateway::DomainName
Properties:
DomainName: localhost:4000
EndpointConfiguration:
Types:
- REGIONAL
RegionalCertificateArn:
Ref: FrontendCertificateapilocalchild7173C752
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/CustomDomain/Resource
FrontendApiGatewaylocalfrontendapilocalCustomDomainMaplocalFrontendApiGatewaylocalfrontendapilocal22D5CF714E8C516E:
Type: AWS::ApiGateway::BasePathMapping
Properties:
DomainName:
Ref: FrontendApiGatewaylocalfrontendapilocalCustomDomainB4D30972
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
Stage:
Ref: FrontendApiGatewaylocalfrontendapilocalDeploymentStageprodBC56BC1F
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/CustomDomain/Map:--=>localFrontendApiGatewaylocalfrontendapilocal22D5CF71/Resource
FrontendApiGatewaylocalfrontendapilocalOPTIONS37358616:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: OPTIONS
ResourceId:
Fn::GetAtt:
- FrontendApiGatewaylocalfrontendapilocal5C7648A5
- RootResourceId
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
AuthorizationType: NONE
Integration:
IntegrationResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
method.response.header.Access-Control-Allow-Origin: "'http://localhost:3000'"
method.response.header.Vary: "'Origin'"
method.response.header.Access-Control-Allow-Methods: "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'"
method.response.header.Access-Control-Allow-Credentials: "'true'"
StatusCode: "204"
RequestTemplates:
application/json: "{ statusCode: 200 }"
Type: MOCK
MethodResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Origin: true
method.response.header.Vary: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Credentials: true
StatusCode: "204"
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/OPTIONS/Resource
FrontendApiGatewaylocalfrontendapilocalorder190D5B05:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Fn::GetAtt:
- FrontendApiGatewaylocalfrontendapilocal5C7648A5
- RootResourceId
PathPart: order

RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/Resource
FrontendApiGatewaylocalfrontendapilocalorderOPTIONS93DCA01D:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: OPTIONS
ResourceId:
Ref: FrontendApiGatewaylocalfrontendapilocalorder190D5B05
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
AuthorizationType: NONE
Integration:
IntegrationResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
method.response.header.Access-Control-Allow-Origin: "'http://localhost:3000'"
method.response.header.Vary: "'Origin'"
method.response.header.Access-Control-Allow-Methods: "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'"
method.response.header.Access-Control-Allow-Credentials: "'true'"
StatusCode: "204"
RequestTemplates:
application/json: "{ statusCode: 200 }"
Type: MOCK
MethodResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Origin: true
method.response.header.Vary: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Credentials: true
StatusCode: "204"
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/OPTIONS/Resource
FrontendApiGatewaylocalfrontendapilocalorderpdf8ADB696B:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Ref: FrontendApiGatewaylocalfrontendapilocalorder190D5B05
PathPart: pdf
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/Resource
FrontendApiGatewaylocalfrontendapilocalorderpdfOPTIONS25C6B290:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: OPTIONS
ResourceId:
Ref: FrontendApiGatewaylocalfrontendapilocalorderpdf8ADB696B
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
AuthorizationType: NONE
Integration:
IntegrationResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
method.response.header.Access-Control-Allow-Origin: "'http://localhost:3000'"
method.response.header.Vary: "'Origin'"
method.response.header.Access-Control-Allow-Methods: "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'"
method.response.header.Access-Control-Allow-Credentials: "'true'"
StatusCode: "204"
RequestTemplates:
application/json: "{ statusCode: 200 }"
Type: MOCK
MethodResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Origin: true
method.response.header.Vary: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Credentials: true
StatusCode: "204"
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/OPTIONS/Resource
FrontendApiGatewaylocalfrontendapilocalorderpdfidC7654574:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Ref: FrontendApiGatewaylocalfrontendapilocalorderpdf8ADB696B
PathPart: "{id}"
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/{id}/Resource
FrontendApiGatewaylocalfrontendapilocalorderpdfidOPTIONS4050D92E:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: OPTIONS
ResourceId:
Ref: FrontendApiGatewaylocalfrontendapilocalorderpdfidC7654574
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
AuthorizationType: NONE
Integration:
IntegrationResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
method.response.header.Access-Control-Allow-Origin: "'http://localhost:3000'"
method.response.header.Vary: "'Origin'"
method.response.header.Access-Control-Allow-Methods: "'OPTIONS,GET,PUT,POST,DELETE,PATCH,HEAD'"
method.response.header.Access-Control-Allow-Credentials: "'true'"
StatusCode: "204"
RequestTemplates:
application/json: "{ statusCode: 200 }"
Type: MOCK
MethodResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Origin: true
method.response.header.Vary: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Credentials: true
StatusCode: "204"
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/{id}/OPTIONS/Resource
FrontendApiGatewaylocalfrontendapilocalorderpdfidGETApiPermissionlocalFrontendApiGatewaylocalfrontendapilocal22D5CF71GETorderpdfidEFB3D8F0:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName:
Fn::GetAtt:
- FrontendLambdasApilocalgetPdfOrderFunctionC0BB63A2
- Arn
Principal: apigateway.amazonaws.com
SourceArn:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":execute-api:us-east-1:"
- Ref: AWS::AccountId
- ":"
- Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
- /
- Ref: FrontendApiGatewaylocalfrontendapilocalDeploymentStageprodBC56BC1F
- /GET/order/pdf/*
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/{id}/GET/ApiPermission.localFrontendApiGatewaylocalfrontendapilocal22D5CF71.GET..order.pdf.{id}
FrontendApiGatewaylocalfrontendapilocalorderpdfidGETApiPermissionTestlocalFrontendApiGatewaylocalfrontendapilocal22D5CF71GETorderpdfid601C4318:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName:
Fn::GetAtt:
- FrontendLambdasApilocalgetPdfOrderFunctionC0BB63A2
- Arn
Principal: apigateway.amazonaws.com
SourceArn:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":execute-api:us-east-1:"
- Ref: AWS::AccountId
- ":"
- Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
- /test-invoke-stage/GET/order/pdf/*
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/{id}/GET/ApiPermission.Test.localFrontendApiGatewaylocalfrontendapilocal22D5CF71.GET..order.pdf.{id}
FrontendApiGatewaylocalfrontendapilocalorderpdfidGET755A64B2:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: GET
ResourceId:
Ref: FrontendApiGatewaylocalfrontendapilocalorderpdfidC7654574
RestApiId:
Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
AuthorizationType: NONE
Integration:
ContentHandling: CONVERT_TO_TEXT
IntegrationHttpMethod: POST
PassthroughBehavior: WHEN_NO_TEMPLATES
Type: AWS_PROXY
Uri:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :apigateway:us-east-1:lambda:path/2015-03-31/functions/
- Fn::GetAtt:
- FrontendLambdasApilocalgetPdfOrderFunctionC0BB63A2
- Arn
- /invocations
Metadata:
aws:cdk:path: local/Frontend/ApiGateway-local/frontend-api-local/Default/order/pdf/{id}/GET/Resource
FrontendLambdaExecRolelocal891E0151:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
Version: "2012-10-17"
ManagedPolicyArns:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/AWSLambda_FullAccess
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/AmazonS3FullAccess
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/AmazonRDSFullAccess
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/AmazonCognitoPowerUser
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/AmazonEC2FullAccess
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/AmazonSESFullAccess
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
RoleName: lambdaExecRole
Metadata:
aws:cdk:path: local/Frontend/LambdaExecRole-local/LambdaExecRole-local/Resource
FrontendLambdasApilocalgetPdfOrderFunctionC0BB63A2:
Type: AWS::Lambda::Function
Properties:
Code:
S3Bucket:
Ref: AssetParametersf0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800cS3Bucket56CC0B0C
S3Key:
Fn::Join:
- ""
- - Fn::Select:
- 0
- Fn::Split:
- "||"
- Ref: AssetParametersf0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800cS3VersionKey001FD9B3
- Fn::Select:
- 1
- Fn::Split:
- "||"
- Ref: AssetParametersf0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800cS3VersionKey001FD9B3
Role:
Fn::GetAtt:
- FrontendLambdaExecRolelocal891E0151
- Arn
Environment:
Variables:
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1"
FunctionName: order_pdf_get-order-pdf
Handler: index.handler
MemorySize: 1024
Runtime: nodejs16.x
Timeout: 900
DependsOn:
- FrontendLambdaExecRolelocal891E0151
Metadata:
aws:cdk:path: local/Frontend/LambdasApi-local/getPdfOrderFunction/Resource
aws:asset:path: /home/ben/development-projects/fee/fee-infra-backend/cdk.out/asset.f0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800c
aws:asset:is-bundled: true
aws:asset:property: Code
CDKMetadata:
Type: AWS::CDK::Metadata
Properties:
Analytics: v2:deflate64:H4sIAAAAAAAA/11Q227CMAz9Ft5DNraJPXPR3mAV+4DKpKYYmqRK3CFU9d/ntFTr9nRuVuyTF/221M8zuMW5Ka7zio66/WIwVyVW3hoMTCcywGjBQYlBt5tfT21ObiI7BTWVQm5w1+0BI69qSjMTujLGN47VFuvK3y0KFXeiZHvZPzyQrbdAbg+29yZqDREz4PMO6ppcmdL/lqz1TTCYfLVDPvsijT3YmD4O7HmnCKyc7qvBFuxUBfZYgBQ/uQyDpRjJuxR/NM6w8HEkd77AS9T7HsZUxdccYkSOepVAtF435oqc7urSQ58N1w2rPk61H30yCNKUMfw9MW3Rl/j0vVjqxbtezC6RaB7kV8miPgz4A2efNcrZAQAA
Metadata:
aws:cdk:path: local/CDKMetadata/Default
Outputs:
FrontendApiGatewaylocalfrontendapilocalEndpointAFD88AF3:
Value:
Fn::Join:
- ""
- - https://
- Ref: FrontendApiGatewaylocalfrontendapilocal5C7648A5
- .execute-api.us-east-1.
- Ref: AWS::URLSuffix
- /
- Ref: FrontendApiGatewaylocalfrontendapilocalDeploymentStageprodBC56BC1F
- /
Parameters:
AssetParametersf0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800cS3Bucket56CC0B0C:
Type: String
Description: S3 bucket for asset "f0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800c"
AssetParametersf0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800cS3VersionKey001FD9B3:
Type: String
Description: S3 key for asset version "f0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800c"
AssetParametersf0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800cArtifactHash2F045658:
Type: String
Description: Artifact hash for asset "f0593e76148ddf4e25df024c8a632facbd1880dc86834ff2929fb4ce320e800c"
```

### Observed result:

The response I get through Postman is however not formatted correctly and I get the following error message when the PDF response opens:

Failed to load PDF file.

When I deploy the code to AWS it works absolutely fine, which is why I believe this is an issue with SAM.

### Expected result:

I expect to get the properly formatted PDF back since I have added `BinaryMediaTypes` to my API config

### Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

1. OS: Ubuntu
2. Sam version 1.56.1
3. AWS region: US-East-1

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.