DEV Community

Roman Leventov
Roman Leventov

Posted on

Enable CORS with custom headers for an AWS Lambda function behind API Gateway in Serverless framework

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)

Collapse
 
dnorth profile image
Danny North

Exactly what I was looking for, thanks!

Collapse
 
idandeeto profile image
IdanDeeto

Is there a way to set a default CORS header instead of adding it one by one to all methods?