amazon-web-servicescorsaws-api-gateway-v2

API Gateway v2 not returning CORS headers from OPTIONS call


Got an API Gateway v2 that is pointing at a Lambda that is running into CORS issues when I send a POST from a website running on localhost. As part of the troubleshooting I'm mimicking a preflight request with curl. It's not working how I'd expect.

Here is my CORS settings in API gateway (dev only, not prd):

enter image description here

CORS section of aws apigatewayv2 get-api --api-id=redacted

    "CorsConfiguration": {
        "AllowCredentials": false,
        "AllowHeaders": [
            "content-type"
        ],
        "AllowMethods": [
            "HEAD",
            "OPTIONS",
            "POST"
        ],
        "AllowOrigins": [
            "*"
        ],
        "MaxAge": 600
    },

I'm using this script to query it:

source='localhost'
dest='https://redacted.execute-api.us-west-2.amazonaws.com/redacted/'
verb='POST'
echo $source $dest $verb
curl -I -X OPTIONS \
  -H "Origin: ${source}" \
  -H "Access-Control-Request-Method: ${verb}" \
  -H "Access-Control-Request-Headers: origin" \
  "${dest}"

Response is:

HTTP/2 204
date: Thu, 23 Sep 2021 18:03:25 GMT
apigw-requestid: GIMpJhH4PHcES5g=

From reading MDN docs here and this answer here I'd expect API Gateway to be returning a response that has Access-Control-Allow-Origin in it. But I'm getting nothing back. Changing source to include http:// didn't change the outcome (and I wouldn't expect it to, I think CORS only cares about domains in this case).

Note that a lot of answers involve "you forgot to deploy it" -- but API Gateway v2 defaults to "auto deploy" and this instance is using that default -- it's deployed every time you change it.

Note: I have set 'Access-Control-Allow-Origin': '*' and "Content-Type": "application/json", in my lambda that API gateway is pointing at, but I think this isn't even getting that far so the lambda isn't part of the problem right now. Am I misunderstanding?

How do I check CORS on AWS API Gateway v2 with curl?

Also should I create a tag for aws-api-gateway-v2? It's a bit different than v1, enough so that Terraform uses a different module for it.


Solution

  • This came down to rejected headers. Short version: any rejected header in API Gateway will cause a 404. This is a working curl:

    curl 'https://redacted.execute-api.us-west-2.amazonaws.com/redacted' -I \
      -X 'OPTIONS' \
      -H 'authority: redacted.execute-api.us-west-2.amazonaws.com' \
      -H 'accept: */*' \
      -H 'access-control-request-method: POST' \
      -H 'access-control-request-headers: content-type' \
      -H 'origin: http://localhost:8080' \
      -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' \
      -H 'sec-fetch-mode: cors' \
      -H 'sec-fetch-site: cross-site' \
      -H 'sec-fetch-dest: empty' \
      -H 'referer: http://localhost:8080/' \
      -H 'accept-language: en-US,en;q=0.9' \
      --compressed