AWS API Gateway - CORS + POST not working

泪湿孤枕 提交于 2019-11-26 20:12:26

问题


CORS is really driving me crazy and I'm really out of ideas as of what to try to make it work.

I have created a simple APIG Api with 1 resource called 'abc' and added 2 methods GET and POST both with Authorization set to NONE and API Key Required set to false, everything deployed to a stage called 'dev'.

Of course I enabled CORS on both methods and I see the 3 headers Access-Control-Allow-Origin, Access-Control-Allow-Headers and Access-Control-Allow-Methods added to the OPTIONS method and the Access-Control-Allow-Origin added to the POST and GET methods.

Both calls are mapped to the same lambda function that simply outputs a 'Hello from Lambda' text to the console.

Then I have created a simple html page I hosted as a static website on S3, pointed a domain to it using Route53 and started testing the API using jQuery $.ajax to make the calls.

All seems easy, straightforward and exactly as explained in the docs, except only the GET works and outputs the text to the console as expected. The POST version results in the following error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access. The response had HTTP status code 400.

The preflight call works and returns 200 OK and all headers are there, but the POST call returns that error and a 400 Bad Request.

Please any help is really appreciated, I hope the AWS team is watching too...

Thanks guys.


EDITED - Copied from Google Chrome:

POST Raw Request Headers:

POST /dev/urls HTTP/1.1
Host: kykul1mshe.execute-api.us-east-1.amazonaws.com
Connection: keep-alive
Content-Length: 73
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Content-Type: application/json
Referer: http://example.com/dev.html
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

POST Raw Response Headers:

HTTP/1.1 400 Bad Request
Date: Fri, 19 Aug 2016 02:14:16 GMT
Content-Type: application/json
Content-Length: 177
Connection: keep-alive
x-amzn-RequestId: a1160e45-65b2-11e6-9766-cd61e49fbcdb
X-Cache: Error from cloudfront
Via: 1.1 d64756b4df47ce24d6c62b5a8de97e87.cloudfront.net (CloudFront)
X-Amz-Cf-Id: N9mf7apicKbSM_MiZjePbEgZGIFKckWJ3lZljH8iHVKFVTcIIOQuHg==

This returns 400 Bad Request

OPTIONS Raw Request Headers:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:kykul1mshe.execute-api.us-east-1.amazonaws.com
Origin:http://example.com
Referer:http://example.com/dev.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36

OPTIONS Raw Response Headers:

Access-Control-Allow-Headers:Content-Type,X-Amz-Date,Authorization,X-Api-Key,Cache-Control,X-Requested-With
Access-Control-Allow-Methods:POST,OPTIONS
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:79
Content-Type:application/json
Date:Fri, 19 Aug 2016 02:14:16 GMT
Via:1.1 d64756b4df47ce24d6c62b5a8de97e87.cloudfront.net (CloudFront)
X-Amz-Cf-Id:KpGEDmIuf5RHcUnBWuA3oEMZgWHwrjy3SpLuOflRhAD8IIx5vyKGSw==
x-amzn-RequestId:a10bae11-65b2-11e6-bcf7-63b49c24629e
X-Cache:Miss from cloudfront

This returns 200 OK


回答1:


Ok, I found the origin of the problem, which happens to be totally unrelated to APIG, and confirms what @AbhignaNagaraja mentioned, that my APIG was properly configured.

The issue is actually in the way I called jQuery.ajax, which I thought was smart enough to convert my parameters to a JSON string when contentType is 'application/json'. It seems I had to manually stringify the JSON params rather than passing a JSON and having jQuery stringify it.

So this is the bad call:

$.ajax({
        url: myEndpoint,
        type: 'POST',
        crossDomain: true,
        data: {
            url: $('#url').val()
        },
        headers: {
            "X-Api-Key": 'blablabla'
        },
        dataType: 'json',
        contentType: "application/json",
        success: function (data) {
            console.info(data);
        }
    });

And this is the right call:

 $.ajax({
        url: myEndpoint,
        type: 'POST',
        crossDomain: true,
        data: JSON.stringify({
            url: $('#url').val()
        }),
        headers: {
            "X-Api-Key": 'blablabla'
        },
        dataType: 'json',
        contentType: "application/json",
        success: function (data) {
            console.info(data);
        }
    });

This can be a hint if you are debugging such an issue with CORS: just download the AWS APIG SDK and try executing the call using the apigClient provided by AWS and compare headers with the ones you get with your custom client. When examining the 2 sets of headers I got with jQuery and apigClient, I noticed the Request Payload looked different and thats how I realized the format was wrong, then the 400 code and the No 'Access-Control-Allow-Origin' header is present all made sense.

I hope this helps.




回答2:


I had a similar issue, but with lambda proxy integration:

  • CORS activated on AWS API Gateway using the browser

  • lambda-proxy integration activated

When using the lambda proxy integration, you can return custom headers from inside the code of the lambda:

        var result = {
        statusCode: data.statusCode | 200,
        headers: {
          "Access-Control-Allow-Origin": "*"
        },
        body: JSON.stringify(responseBody)
    };
    callback(null, result);

This way you get the CORS header sent. I think there might be a better way to get it to work with the lambda proxy integration without coupling the CORS inside the code of the lambda, please let me know if you know.




回答3:


If you are using proxy integration in API Gateway, then enabling CORS from API Gateway doesn't work. You have to set the Header 'Access-Control-Allow-Origin' from your Lambda code itself.

Its mentioned in the doc.

Python code sample:

    response = {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Origin': '*'
        },
        'body': json.dumps({'message': 'CORS enabled')
    }
    return response



回答4:


I had a similar issue - and it had nothing to do with the way that the API was configured or the POST request that I was making on the front-end. What fixed the problem for me was deploying the API on AWS API Gateway. Once you create an API method/resource, and tie them to a lambda function, they do not auto deploy.

You have to click "Actions" and then "Deploy API" in order to access these MicroServices from the front-end.




回答5:


to resolve this i present to you my config of the Post configuration in apy gateway

Option method - Integration REsponse - Headers Mapping

X-Requested-With '*'
Access-Control-Allow-Headers 'Content-Type,x-requested-with,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods'
Access-Control-Allow-Origin 'http://localhost:4200'
Access-Control-Allow-Methods 'POST,OPTIONS'

Post Method - Integration Response - Headers Mapping

Access-Control-Allow-Origin "*" ---> can be changed by your ip obviously

I hope this helps you




回答6:


I was also stuck in this error, and after digging, I found that in non 2XX responses, the API was not giving Access-Control-Allow-Origin header in the response. Hence, while the OPTION method and successful (2XX) responses had this header, the 4XX and 5XX did not. One can also confirm this using PostMan and inspecting the headers of the bad response.

After tweaking with configuration I made sure to return that header in all responses.




回答7:


There have been many posts that direct you to make sure the lambda function is returning the appropriate CORS headers, and they are correct. However, it is also critical that the json object is stringified using JSON.stringify(). It seems that Postman does this for us, so it is misleading when the Postman request and the $.ajax request send the same json object; yet one succeeds and one fails.



来源:https://stackoverflow.com/questions/38987256/aws-api-gateway-cors-post-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!