`No Access-Control-Allow-Origin` header is present - AngularJS - javascript

So, when I looked up the error, I see mostly it has something to do with with the webservice.
The problem is that I cant touch the webservice. However, using Postman extension on chrome it returns data just fine. So, i tend to believe that there is something wrong on frontend.
Also, Im using angular and rather at beginner's level, so I might be missing something trivial.
.factory('forecast', ['$http', function($http){
return $http.get('https://link')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}
]);

You will always get the Access-Control-Allow-Origin error if the webservice you are trying to access via REST doesn't have that header set for the response you are aiming to get.
However, most of the times, you can get around it by making a Server -> Server request instead of a Client -> Server (AJAX) request.
For example, if you are using NodeJS as a backend and make the request from there, then send the response back to your client via Node, you should be fine.
EDIT: Also, as stated in the comments (forgot that, thanks), AngularJS's $http service also exposes a $http.jsonp method using which you can get around that. However that only works if the webservice you are trying to access also exposes the information as JSONP in their API.
Documentation on $http.jsonp

Related

POST Request Not Recognizing Headers

I am trying to make a POST request to an AWS Lambda Python Script I have set up.
I have already heard about solving the issue of Access-Control-Allow-Origin by adding a header to the Response from AWS lambda, that looks like Access-Control-Allow-Origin:*, and I implemented this in the code I was working on for the get request. Then when I begun creating a POST request, I did the same thing, so that the new POST request originally looked like this:
def post(event, context):
try:
return dict(
statusCode=200,
headers= {'Access-Control-Allow-Origin': "*"},
body="test"
)
except Exception as ex:
return dict(
statusCode=500,
body=str(ex)
)
And this works, in Chrome's Network-Tab I see that we pass a post request and there is no issue, and the header is recognized properly, allowing Cross-Origin calls. But this is pretty much just the GET request I have which is already set up and working. So when I update it to be more similar to a POST METHOD and do what I want the problems begin.
So my code, that I want to be performed in the POST request is simple, I should be able to make the request like such,
def post(event, context):
try:
result=str(event.get("inputOne") + event.get("inputTwo"))
return dict(
statusCode=200,
headers= {'Access-Control-Allow-Origin': "*"},
body=result
)
except Exception as ex:
return dict(
statusCode=500,
body=str(ex)
)
When I test this in the AWS Lambda Management console, my code works, and I get the expected response back in the body.
But then when I try and call the POST endpoint from my React Site, I once again am getting the error:
Access to XMLHttpRequest at 'THE_POST_URL' from origin
'http://localhost:XXX' has been blocked by CORS policy: No 'Access-
Control-Allow-Origin' header is present on the requested resource.
So for some reason, when the body variable is not just a simple string in quotes like "this" <- it fails. I believe this has to do with the Content-Type in the request being of the form application/json;charset=UTF-8 while my request only accepts (as it says in dev-tools) application/json however even when trying to add the headers to accept this format for content-type, I am still getting the same issues.
I am not entirely sure why the header worked on the GET request, but not the POST request, and would appreciate anyone being able to help teach me, thank you!
EDIT: I have also tried adding 'Access-Control-Allow-Methods': "OPTIONS,GET,POST" to the headers of the post response, but this did not work either.
So after reading through the comments on my question, I decided it was worth going and taking a harder look at the way I had my API Gateway, and Lambda service set up on AWS.
I began using the curl utility in order to try and test my post-call from a terminal utility and found that there it was also failing, but I was able to use CloudWatch to debug, the issue and finally get it working.
The problem that I was facing with my curl Request was that I was not properly formatting the JSON input, but even when I was the Lambda was transforming the event improperly, not resulting in a Dict, as expected.
The curl call I was using can be seen:
curl -X POST https://myURL.execute-api.myREGION.amazonaws.com/stage/yourPOST \
-d '{"inputOne":80000,"inputTwo":85}'
But in order to read that input properly, and then work with it, I had to update my code in the Lambda to reflect parsing the input properly, this updated lambda code can be found here. The event object that you are passing to this lambda is a DICT object, so on the first line, we use JSON.loads to decode the "body" value of the event, into a dict that we store as body. Then to get the value of the two attributes, we use the command body.get("yourKey").
def yourPOST(event, context):
body=json.loads(event["body"])
a=body.get("inputOne")
c=body.get("inputTwo")
After making these changes the call from my React site works without error! If anyone has any questions feel free to comment, I hope this helped!

AngularJS - $http get returns error with status 0?

I've an AngularJS application in which I'm trying to get an XML data with $http get from a server say http://example.com/a/b/c/d/getDetails?fname=abc&lname=def (this when accessed manually by entering the link in a browser shows a tree structure of the XML file).
When I run the application the data from that link is not fetched. Instead its showing an error with status 0.
//url = http://example.com/a/b/c/d/getDetails?fname=abc&lname=def
$http.get(url).success(function (data){
alert("Success");
deferred.resolve(data);
}).error(function (data, status){
console.log("Error status : " + status);
});
I'm not sure why the $http.get fails and goes to the error function returning status 0.
But if I pass an URL to the local server which has a JSON object, it works.
Is the problem because of me trying to access the XML file from a different domain(CORS issue?) or something else?
Please help me out!
You have HTTP access control (CORS) issues .
The server answering your REST requests MUST include the headers specified by CORS in order to allow Angular to consume properly the response. Essentially this means including the Access-Control-Allow-Origin header in your response, specifying the servers from where the request comes from, that are allowed. (ref)
There is directive Angular allows one to get/set the whitelists and blacklists used to ensure that the URLs used for sourcing Angular templates are safe.
yes you got it right, its because default content-type for $http is “application/json” if you want to change the request data or response data you can change it with the help of tranformRequest and tranformResponse. you can find more information on it here
also i find an article on implementation of tranformRequest change post data from json to form post in angularjs

AngularJS: Unable to get responseHeaders after a $resource $save

I'm performing the following $save which calls my angularJS $resource and POSTs to my API. I'm able to debug into my success callback handler and the object is actually created in my API.
myObj.$save({}, function (value, responseHeaders) {
myObj.someSuccessFunction();
}, function (responseText) {
myObj.someFailureFunction();
});
I'm unable to retrieve anything from the "responseHeaders" param. "responseHeaders()" returns an empty object. I would like to pull the "location" response header like this: responseHeaders("Location").
It's worth noting that the Response is filled in when debugging in chrome. The "responseHeaders" object is failing to be populated for some reason.
How can we get these responseHeaders?
Thanks!
Could it be a CORS issue? If you are making the call across a domain, be sure to include cors.exposed.headers in the pre-flight OPTIONS call.
If it is a cross domain call you have to add the following header in your response headers:
Access-Control-Expose-Headers: Location
With this, the browser is capable to expose your customs headers an read it angular.
I have the same issue with spring security 4.2 CORS filter and AngularJS. My client app built using Angular JS not able to read customer authentication token from response header sent by spring rest api.
I could resolve the issue by exposing below headers.
config.addExposedHeader("Origin");
config.addExposedHeader("X-Requested-With");
config.addExposedHeader("X-AUTH-TOKEN");
config.addExposedHeader("Content-Type");
config.addExposedHeader("Accept");
config.addExposedHeader("Authorization");
config.addExposedHeader("Location");
After the above fix. My Angular code able to read headers.

Angularjs http.get failure (but I see the data was returned)

I'm walking thru the Angularjs phones tutorial and want to get the phones JSON from a remote server.
$http.get('http://myserver.com/phones.json').success(function(data) {
$scope.phones = data;
});
This failed due to CORS, I was sending an OPTIONS not a GET request, so I added this first line to the controller
delete $http.defaults.headers.common['X-Requested-With'];
I can see now in Charles that a GET not OPTIONS request is being made to myserver.com, and that the phones JSON is in the response. But the http.get is still failing with status 0 and 'data' is null.
Not sure what to try next. Any insights appreciated.
It should not be making an OPTIONS request for a GET, so that sounds right. I think what you want to do is:
$http.get('http://myserver.com/phones.json').then(function(data) {
$scope.phones = data;
}, function(err) { alert('Oh no! An error!'});
I think you want to use then(), which takes two functions as arguments — the first for success, and the second for error. $http.get() returns a promise which is acted upon by then().
Also, you probably want to use $resource instead of $http. It provides a higher level of abstraction, and allows for a more reusable style, http://docs.angularjs.org/api/ngResource.$resource
EDIT:
Check out the angular debug tool here. It shows you what is available in scopes, and shows performance data.
Well, if you are making a cross domain request, it is right to make a OPTION request as a pre-flight request to know if you are allowed to.
If the CORS fails your browser will receive the data but it'll throw an error.
So, either you put your html in the same domain or add the CORS to your backend (which is more difficult).
Here's a good tutorial which implements cross-domain GETS using the $http.jsonp method. No hacks to the headers.
http://net.tutsplus.com/tutorials/javascript-ajax/building-a-web-app-from-scratch-in-angularjs/

jQuery JSONP request causing TFL API to throw 400

I'm using jQuery .getJSON to get data from TFL's (transport for london) API.
However adding the ?callback=? parameter to the request causes the API to throw a 400 (Bad Request) error because it is very strict about what parameters it accepts. I.E the api can't recognise '?callback' as a valid parameter and therefore freaks out.
Is there another completely different way of doing this? Somehow getting the api response and parsing it myself for example. I'm new to JS and jQuery so apologies if I'm missing something super obvious!
var busStopAPI = 'http://countdown.api.tfl.gov.uk/interfaces/ura/instant_V1?StopCode1=56094&VisitNumber=1&ReturnList=StopCode1,StopPointName,LineName,DestinationText,EstimatedTime,DirectionId';
$.getJSON(busStopAPI, this.busStopSuccess).fail(this.busStopFailure);
p.s. I've tried the other .ajax() data types but they all throw 'Access-Control-Allow-Origin' errors.
You are trying to add "callback" because you want to use JSONP, right?... and you want to do that because if you don't you get a cross-domain error, right?
I would suggest to create a local web service proxy in your server that calls TFL's api and supply data to your UI. In that way you do not have to use JSONP and do not have to worry about cross-domain issues. (more info)
FYI, there are other approaches, but I personally prefer a proxy service when the api does not support JSONP callbacks.
Hope it helps.

Categories