AWS API Gateway supports CORS for OPTIONS only when using SAM (without Lambda proxy integration)


I’m using AWS Serverless for building a small site with around 15 Lambda functions.
My Cloudformation stack is completely built using SAM.
I’m NOT using Lambda proxy integration.

The Api section in the SAM yaml template config looks like this:

When I deploy this SAM yaml template, I see that my ApiGateway created the OPTIONS verb for all methods and when I shoot a request with the OPTIONS verb, I do see the CORS headers correctly.

The problem is that the other verbs (e.g. POST) don’t add those headers to their response as the OPTIONS request did and when I run my api from the browser I get the cross origin policy error in my console.

So my current workaround was to add the CORS header using integrated responses to specific status codes, but I cannot and dont want to handle that for 15 methods and I want to support all response status codes (e.g. 4xx\5xx etc.).

My questions:

  1. Am I doing anything wrong here or is this a SAM bug?
  2. If this is a bug, is there any workaround other from adding the headers using integrated responses (or from my code)?
  3. Is there a way I can add headers “globally” from an Api Gateway? Or support some kind of global integrated responses?


If you are using Lambda with Proxy Integrations, you need to specify the CORS Origin in your HTTP response.

For Lambda or HTTP proxy integrations, you can still set up the
required OPTIONS response headers in API Gateway. However, you must
rely on the back end to return the Access-Control-Allow-Origin headers
because the integration response is disabled for the proxy

All responses from Lambda need to have these headers and status code, but you could extract that to a shared library to reduce code duplication. Errors handled by API-G will have the headers added automatically.

You probably already have this, but the NodeJS pattern is like this:

If you really don’t want to do this then you can turn off Lambda-Proxy Integration, but that means that all request response payloads need to be handled in API-G instead of Lambda. IMO this provides much less flexibility and more configuration required to achieve the same results.

Here is an interesting comparison of the two approaches.

Leave a Reply