Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS API Gateway - CORS + POST not working

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

like image 931
HBR Avatar asked Aug 17 '16 02:08

HBR


People also ask

How do I fix the CORS issue in AWS API gateway?

Confirm the cause of the error There are two ways to confirm the cause of a CORS error from API Gateway: Create an HTTP Archive (HAR) file when you invoke your API. Then, confirm the cause of the error in the file by checking the headers in the parameters returned in the API response.

Why CORS is not working?

Or, your API fails and shows a CORS error in the console. This happens because the same-origin policy is part of the browser's security model which allows websites to request data from APIs of the same URL but blocks those of different URLs. Browsers do this by adding an ORIGIN key in the request.

How do I check if CORS is enabled in AWS API gateway?

You can test your API's CORS configuration by invoking your API, and checking the CORS headers in the response. The following curl command sends an OPTIONS request to a deployed API.


2 Answers

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 
like image 51
Dawn T Cherian Avatar answered Sep 19 '22 07:09

Dawn T Cherian


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.

like image 28
HBR Avatar answered Sep 19 '22 07:09

HBR