10

An AWS Lamba function (NodeJS) returning 3 HTTP headers: aaa, Access-Control-Allow-Origin and bbb was created:

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: { "aaa":"aaa", "Access-Control-Allow-Origin":"*", "bbb":"bbb" },
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

The function is integrated into a HTTP API (not REST API). In the HTTP API Gateway Configuration, Section "Configure CORS", the HTTP header "Access-Control-Allow-Origin" was set to "*". Please see the screenshot:

Gateway Config

The command "curl -i https://xxxxxxxxxx.execute-api.eu-central-1.amazonaws.com" proves that the HTTP Header Access-Control-Allow-Origin is explicitly removed, because only HTTP headers aaa and bbb are returned:

HTTP/2 200 
date: Tue, 14 Apr 2020 11:01:58 GMT
content-type: text/plain; charset=utf-8
content-length: 20
aaa: aaa
bbb: bbb
apigw-requestid: K-S2EjVWliAEJKw=

Why on earth is this header still not present, even after "Configure CORS" was done?

(I'm googling now for more than two days in order to find a solution and it makes me go nuts)

John Steel
  • 121
  • 1
  • 6

3 Answers3

10

As per Configuring CORS for an HTTP API -

If you configure CORS for an API, API Gateway ignores CORS headers returned from your backend integration.

That's why the CORS headers from your Lambda (integration) are being ignored. This is one of the differences between the new HTTP APIs from the original REST APIs. In case of these APIs -

For a CORS request, API Gateway adds the configured CORS headers to the response from an integration.

When you do a simple curl, that is not actual doing a cross-origin request. Hence, you don't see the CORS headers that would be set by the HTTP API. To verify if a CORS request works, I passed an Origin header in the below request and I can see the CORS headers along with my custom headers from Lambda -

$ curl -v -X GET https://$API_ID.execute-api.$AWS_REGION.amazonaws.com -H "Origin: https://www.example.com"

< HTTP/2 200
< date: Tue, 14 Apr 2020 18:02:26 GMT
< content-type: text/plain; charset=utf-8
< content-length: 18
< aaa: aaa
< bbb: bbb
< access-control-allow-origin: https://www.example.com
< access-control-expose-headers: date, x-api-id

Below is a snippet of my CORS configuration on the API. I added Access-Control-Allow-Origin value as https://www.example.com and passed this as a part of the Origin header in my curl request. Such a request would qualify as CORS.

enter image description here

Suraj Bhatia
  • 1,233
  • 3
  • 13
  • 29
  • This is not working when I try it. Are you sure this is enough? – Simon Guldstrand Apr 15 '20 at 12:38
  • @SimonGuldstrand Can you share sample curl request and output? Was your API deployed with the latest change? – Suraj Bhatia Apr 15 '20 at 17:03
  • Yes it was deployed, no more CORS settings on the API itself. See image: https://imgur.com/a/GaIuocq Can we chat somewhere and I will link the output from curl etc – Simon Guldstrand Apr 15 '20 at 17:12
  • @SimonGuldstrand Why are your CORS settings blank? Aren't you trying to set CORS headers here? – Suraj Bhatia Apr 15 '20 at 18:52
  • @SurajBhatia Thank you a million times! Is it CORS official standard to only send the Access-Control-Allow-Origin HTTP header, when the request contains an Origin HTTP header, or is this an AWS special behavior? – John Steel Apr 15 '20 at 19:04
  • @JohnSteel It's in general how CORS works (nothing specific to AWS). Read more about Origin header here https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin – Suraj Bhatia Apr 15 '20 at 21:05
7

For POST/PUT requests, you'll need to white list the content-type header. Putting the wildcard doesn't do the trick for some reason, you need to explicitly whitelist it.

apigw configuration

Elad Levy
  • 291
  • 3
  • 8
  • 1
    Life saver! Thanks a million Elad for your comment, I've been turning around in circles when only that specific content-type allowed header was required to be updated – Clorichel Jan 27 '21 at 14:54
7

For Googlers:

If your OPTIONS preflights succeed but no Access-Control- headers present, and if you are testing using CURL, take extra attention to spell required headers for a preflight:

  • Access-Control-Request-Method: GET
  • Access-Control-Request-Headers: authorization
  • Origin: https://theaws.blog

If wrongly spelt, OPTIONS succeeds with 204 No Content, but no Access-Control- headers thus render the preflight result invalid.

Also check you have enough scope for the parameters, as long as your requested method and headers are a subset of the parameter, you will get Access-Control- headers. If not, you will get 204 No Content instead, which I would say it's not very informative!

dz902
  • 4,782
  • 38
  • 41