I have a sample template, which is creating an AWS Lambda function and an API Gateway,
The issue that I'm facing is the template is able to enable CORS, but it seems to be wrong as on calls from a frontend application still receive the CORS error.
Following is the template -
AWSTemplateFormatVersion: '2010-09-09'
Description: AWS API Gateway with a Lambda Integration
Parameters:
CorsOrigin:
Type: String
Default: "'*'"
CorsHeaders:
Type: String
Default: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
CorsMethods:
Type: String
Default: "'OPTIONS,POST'"
Resources:
BusinessLambda:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
def handler(event, context):
response = {
'isBase64Encoded': False,
'statusCode': 200,
'headers': {},
'multiValueHeaders': {},
'body': 'Hello, World!'
}
return response
Description: AWS Lambda function
FunctionName: 'businessLambda'
Handler: index.handler
MemorySize: 128
Role: 'arn:aws:iam::awsAccountId:role/service-role/TestRole'
Runtime: python3.7
Timeout: 15
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
ApiKeySourceType: HEADER
Description: An API Gateway with a Lambda Integration
EndpointConfiguration:
Types:
- EDGE
Name: api-gw
ApiGatewayResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt ApiGatewayRestApi.RootResourceId
PathPart: 'lambda'
RestApiId: !Ref ApiGatewayRestApi
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ApiKeyRequired: false
AuthorizationType: NONE
HttpMethod: POST
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: "POST"
Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${!stageVariables.lambdaAlias}/invocations'
IntegrationResponses:
- StatusCode: 200
ResponseTemplates:
application/json: $input.json('$')
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
RequestTemplates:
application/json: $input.json('$')
MethodResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: true
method.response.header.Access-Control-Allow-Methods: true
method.response.header.Access-Control-Allow-Origin: true
StatusCode: '200'
OperationName: 'lambda'
ResourceId: !Ref ApiGatewayResource
RestApiId: !Ref ApiGatewayRestApi
APIGatewayOptionsMethod:
Type: "AWS::ApiGateway::Method"
Properties:
ResourceId: !Ref ApiGatewayResource
RestApiId: !Ref ApiGatewayRestApi
AuthorizationType: NONE
HttpMethod: OPTIONS
Integration:
Type: MOCK
IntegrationResponses:
- ResponseParameters:
method.response.header.Access-Control-Allow-Headers: !Ref CorsHeaders
method.response.header.Access-Control-Allow-Methods: !Ref CorsMethods
method.response.header.Access-Control-Allow-Origin: !Ref CorsOrigin
ResponseTemplates:
application/json: ''
StatusCode: '200'
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
application/json: '{"statusCode": 200}'
MethodResponses:
- ResponseModels:
application/json: 'Empty'
ResponseParameters:
method.response.header.Access-Control-Allow-Headers: false
method.response.header.Access-Control-Allow-Methods: false
method.response.header.Access-Control-Allow-Origin: false
StatusCode: '200'
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
Properties:
DeploymentId: !Ref ApiGatewayDeployment
Description: API GW Stage dev
RestApiId: !Ref ApiGatewayRestApi
StageName: 'dev'
Variables:
'lambdaAlias' : 'businessLambda'
GWLambdaPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: "lambda:InvokeFunction"
FunctionName: !Ref BusinessLambda
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/POST/lambda"
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: APIGatewayOptionsMethod
Properties:
Description: Lambda API Deployment
RestApiId: !Ref ApiGatewayRestApi
Outputs:
test:
Value: !Ref ApiGatewayRestApi
Script to test the endpoint from browser console -
let url = "enterUrlHere";
fetch(url, {
method : "POST"
})
.then(function(response) {
console.log('success =>\n', response);
})
.catch(function(error) {
console.log('error =>\n', error);
});
Error -
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Reference -
Enable CORS for API Gateway in Cloudformation template