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?