To properly enable CORS with custom headers for a Lambda function deployed behind API Gateway using Serverless framework, you need to do three separate things:
Add cors
configurations to HTTP points of the function definitions in your serverless.yml
This includes CORS headers to preflight OPTIONS
requests to your API:
functions:
getProduct:
handler: bin/get_product
events:
- http:
path: product/{id}
method: get
cors:
origin: "*"
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- <your-custom-header-goes-here>
Add resources
section to serverless.yml
to include CORS headers in API Gateway-level error responses
Such as due to expired authentification token, unauthorized access, or 404:
resources:
Resources:
GatewayResponseDefault4XX:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent,<your-custom-header-goes-here>'"
ResponseType: DEFAULT_4XX
RestApiId:
Ref: 'ApiGatewayRestApi'
GatewayResponseDefault5XX:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent,<your-custom-header-goes-here>'"
ResponseType: DEFAULT_5XX
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType
fields control what type of responses the corresponding resource section applies to. If you don't want to include CORS headers in every 4XX or 5XX error response, you can find some more specific ResponseTypes here.
Note: GatewayResponseDefault4XX
and GatewayResponseDefault5XX
just resource names and have no significance.
Include CORS headers in the normal responses in your lambda handler
Example in Go:
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
rsp, err := apiGatewayAdapter.ProxyWithContext(ctx, req)
rsp.Headers["access-control-allow-origin"] = "*"
rsp.Headers["access-control-allow-headers"] = "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent,<your-custom-header-goes-here>"
return rsp, err
}
Resources:
Top comments (2)
Exactly what I was looking for, thanks!
Is there a way to set a default CORS header instead of adding it one by one to all methods?