AWS API Gateway - CORS + POST not working

CORS is really driving me crazy, and I really have no idea how to try to get it to work.

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

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

Both calls map to the same lambda function, which simply displays the text "Hello from Lambda" on the console.

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

Everything seems simple, straightforward and accurate, as described in the docs, with the exception of only GET and it prints 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.

A preliminary call is made and returns 200 OK, and all the headers are there, but the POST call returns this error and 400 Bad Request.

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

Thanks guys.


EDITED - copied from Google Chrome:

POST 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 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

+7
api cors amazon-web-services aws-api-gateway
source share
4 answers

Well, I found the cause of the problem, which turns out to be completely unrelated to APIG, and confirms that @AbhignaNagaraja mentioned that my APIG was configured correctly.

The problem is that I called jQuery.ajax, which I thought was smart enough to convert my parameters to a JSON string when the contentType is "application / json". It seems I had to manually compose the JSON parameters, rather than passing JSON and binding it to jQuery.

So this is a 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 correct 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 might be a hint if you are debugging such a problem using CORS: just download the AWS APIG SDK and try to make a call using apigClient provided by AWS and compare the headers with those you get with your user client. When looking at the two sets of headers that I received with jQuery and apigClient, I noticed that Request Payload looks different and I realized that the format was wrong and then 400 and No 'Access -Control-Allow-Origin' , all has the meaning.

Hope this helps.

+8
source share

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

  • CORS activated on AWS API Gateway using a browser

  • lambda-proxy integration activated

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

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

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

+4
source share

I had a similar problem - and it had nothing to do with how the API was configured, or the POST request I made in the interface. For me, the problem was deploying the API on the AWS API Gateway. When you create an API method / resource and bind them to a lambda function, they are not automatically deployed.

You need to click "Actions" and then "Deploy API" to access these microservices from the external interface.

+2
source share

There have been many posts that direct you to have the lambda function return the corresponding CORS headers, and they are correct. However, it is also critical that the json object is gated using JSON.stringify (). The Postman seems to be doing this for us, so it is misleading when the Postman request and the $ .ajax request send the same json object; but one succeeds, and one fails.

0
source share

All Articles