Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS impossible on AWS Lambda HTTP API Gateway Integration

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)

like image 392
John Steel Avatar asked Apr 13 '20 13:04

John Steel


3 Answers

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

like image 189
Suraj Bhatia Avatar answered Oct 21 '22 02:10

Suraj Bhatia


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

like image 23
Elad Levy Avatar answered Oct 21 '22 03:10

Elad Levy


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!

like image 31
dz902 Avatar answered Oct 21 '22 04:10

dz902