Unable to Display JSON Data due to CORS in angularjs - angularjs

I'm trying to create a demo usage of an api in angularjs and I came across this problem.
My Code looks like this:
app.js and index.html
var app = angular.module("ytsApp",['ngRoute','ngResource']);
app.controller('MoviesCtrl',['$scope','movies',function($scope,movies){
movies.get(function(data){
alert(data);
});
}]);
app.factory('movies',['$resource',function($resource){
return $resource('https://yts.ag/api/v2/list_movies.json',{
'sort_by': 'year',
'limit': '15'
},{
'load': {
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
});
}]);
<!DOCTYPE html>
<html ng-app="ytsApp">
<head>
<title>The Official Home of YIFY Movie Torrent Downloads - YIFY</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular-resource.js"></script>
</head>
<body ng-controller="MoviesCtrl">
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
This is the result that is getting displayed in the console while I open that page:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://yts.ag/api/v2/list_movies.json?limit=15&sort_by=year. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
I have searched here and there and tried to edit the headers in several ways and couldn't crack it. I appreciate if anyone help me out with this.

You can use jsonp for your demo which supports cross domain:
$http.jsonp('...').then(...);

Related

AngularJS getting strange response from using get on json rest service with no data

This has been frustrating me a bit. I have a restful services giving JSON data running on the link: http://localhost:51133/API/SalesSystem/
So its running locally on my computer. I can get the data from this service with no problem using my WPF based interface.
Another service I am testing with is this one: http://rest-service.guides.spring.io/greeting
But from my own service something seems to go wrong somehow and I cannot figure out what goes wrong. The spring service gives me a response using a response function, but my service gives a response using a success function function. Very confusing.
Response seems to be:
{"data":null,"status":-1,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"http://localhost:51133/API/SalesSystem/","headers":{"Accept":"application/json, text/plain, */*"}},"statusText":"","xhrStatus":"error"}
I looked it up and it seemed I might be needed to enable Cors, but I am not entirely sure how. I installed it from NuGet, the service is running with Visual Studio, and I added config.EnableCors(); to my WebApiConfig.
My JS script:
angular.module('demo', [])
.controller('Hello', function ($scope, $http) {
$http.get('http://localhost:51133/API/SalesSystem/')
//http://rest-service.guides.spring.io/greeting
//http://localhost:51133/API/SalesSystem/
.then(function (response) {
$scope.hello = 'hello';
$scope.district = response.data;
console.debug(response.data);
console.log(response.data)
}, function success(response) {
$scope.hello = 'hello2';
$scope.district = response;
$scope.rep = response.data;
console.debug(response.data[0]);
$scope.district = response.data[0];
console.log(success.data)
}, function error(response) {
$scope.hello = 'hello3';
$scope.district = error.data;
console.log(error.data)
});
});
My html:
<!doctype html>
<html ng-app="demo">
<head>
<title>Hello AngularJS</title>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/hello.js"></script>
</head>
<body>
<div ng-controller="Hello">
<li>Id: <button>{{hello}}</button></li>
<li>Area: {{district}}</li>
<ul ng-repeat="obj in hello">
<li>Area: {{obj.area}}</li>
</ul>
<p>The ID is {{rep.Id}}</p>
<p>The content is {{hello.Area}}</p>
</div>
</body>
</html>
I am getting it all to work with my WPF based frontend using this service, not sure why it wont work with AngularJS.
The CORS issue has nothing to do with angular. It has got more to do with the browser .
In layman terms , the cors situation is where the browser does not allow responses of other origins than the url to be processed unless the response has a certain set of headers .Of course, it is a bit more complicated than that .Since the response does not have those headers you are getting the CORS issue
For a quick fix you can disable CORS in your browser .
for example :- if you are using chrome you can run it --disable-web-security flag

"No 'Access-Control-Allow-Origin' header present on requested origin" error for res.redirect("http://www.google.com")

I have a simple task on cross origin domain request.So i created a sample express application that have a route to '/redirect', this will redirect to "http://www.google.com". On front end i created a button that have a onclick event , this will request the '/redirect' .
Code i have on server side:
app.get('/redirect',function(req,res){
res.redirect("http://www.google.com");
})
on front end :
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module('myApp',[]);
app.controller('crtl',function ($scope,$http,$timeout){
$scope.fun1 = function(){
$http({
method: 'GET',
url: '/redirect'
}).then(function successCallback(response) {
// console.log(response.data)
console.log("got the request for redirect");
}, function errorCallback(response) {});
}
});
</script>
</head>
<body ng-app="myApp" ng-controller="crtl">
<center><br/>
<button ng-click="fun1()" class="btn">Click Me</button>
</center>
</body>
</html>
You can't use your server to enable direct cross domain access to another domain. The browser simply doesn't work that way. The browser requires the domain that you are trying to access (www.google.com in your example) to be the one that enables cross domain access.
res.redirect() just tells the browser to fetch content from a different source. If the browser doesn't have the cross origin rights to fetch that content, then res.redirect() won't work any better than the browser trying to access it directly.
You could embed the cross origin content in its own iframe and the content could be displayed there, but you wouldn't be allowed access the content from your own Javascript (for the same cross origin reasons).
You could proxy the content from your server which means you could ask your server to get the content for you and your server would fetch it and return it to the browser (via your domain). This works for some uses, but it depends upon what you're trying to do with the content (something you don't share in your question) whether this would satisfy your needs.

Twitter API get tweets - returns CORS origin blocked

I am trying to get tweets from a hashtag. I get following erros Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.twitter.com/oauth2/token. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.twitter.com/1.1/search/tweets.json?f=tweets&q=%23shruthirajoli&src=typd?get=%5Bobject+Object%5D. (Reason: CORS header 'Access-Control-Allow-Origin' missing)
Below is my code:
app.js
var app = angular.module('Twitter', ['ngResource']);
app.controller('TwitterCtrl', function($scope,$http,$resource){
// Create Base64 Object
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},
decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}
var consumerKey = encodeURIComponent('');
var consumerSecret = encodeURIComponent('');
var credentials = Base64.encode(consumerKey + ':' + consumerSecret);
// Twitters OAuth service endpoint
var twitterOauthEndpoint = $http.post('https://api.twitter.com/oauth2/token', "grant_type=client_credentials"
, {headers: {'Authorization': 'Basic ' + credentials, 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'}});
twitterOauthEndpoint.success(function (response) {
// a successful response will return
// the "bearer" token which is registered
// to the $httpProvider
console.log(twitterOauthEndpoint );
app.$httpProvider.defaults.headers.common['Authorization'] = "Bearer " + response.access_token})
.error(function (response) {
// error handling to some meaningful extent
});
$scope.twitter = $resource('https://api.twitter.com/1.1/search/tweets.json?f=tweets&q=%23shruthirajoli&src=typd',
// {action: 'search.json', q:'angularjs', callback:'JSON_CALLBACK'},
{get:{method:'JSONP'}});
$scope.twitterResult = $scope.twitter.get();
});
app.config(function ($httpProvider) {
app.$httpProvider = $httpProvider
});
html
<!doctype html>
<html ng-app="Twitter">
<head>
<script src="http://code.angularjs.org/angular-1.0.0rc4.min.js"></script>
<script src="http://code.angularjs.org/angular-resource-1.0.0rc4.min.js"></script>
<script src="app.js"></script>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css">
</head>
<body>
<div ng-controller="TwitterCtrl">
<table class="table table-striped">
<tr ng-repeat="tweet in twitterResult.results">
<td>{{tweet.text}}</td>
</tr>
</table>
</div>
</body>
</html>
I am running this on localhost:8000, I followed twisters instructions to troubleshoot this. Can someone let me know, if I am making any mistake. thanks.
The reason why you are getting this error is because your making the request through the browser. Browsers don't allow cross domain requests because like #allenru mentioned in the comments below: Servers need to response according to the CORS spec so the browser can proceed with the request.
You can learn more about it here :
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
The proper way to fetch tweets would be making a call to the server and have the server fetch tweets for you.
This also seems like a buggy call.
https://api.twitter.com/1.1/search/tweets.json?f=tweets&q=%23shruthirajoli&src=typd?get=%5Bobject+Object%5D.
Its not normal to have [object + object] in requests. It seems like an object that was not stringified.

No 'Access-Control-Allow-Origin' error from local domain to public API

I'm trying to create an app that will retrieve the stock name, asking and buy price from Yahoo Finance API, using Restangular. I'm having a problem with accessing a public API in the local application I'm creating when I do a GET request. This is the URL with parameters that I'm sending:
http://finance.yahoo.com/d/quotes.csv?s=MSFT+GE&f=nab
Using Postman, this get request returns an array which contains the stock name, asking price and buy price of the stock. Doing the request in postman returns the desired information without any errors.
When I do this request in my local, I get the following error:
XMLHttpRequest cannot load http://finance.yahoo.com/d/quotes.csv?s=MSFT+GE&f=nab. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
The HTML code is as follows:
<html ng-app="app">
<head>
<title>Restangular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="//code.angularjs.org/1.2.27/angular-resource.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="//cdn.rawgit.com/mgonto/restangular/master/dist/restangular.min.js"></script>
</head>
<body>
<div ng-controller="IndexCtrl" ng-cloak>
<ul>
<li ng-repeat="person in people">{{person.Name}}</li>
</ul>
</div>
And the JS:
var app = angular.module('app', ['restangular'])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://finance.yahoo.com/d');
});
app.controller('IndexCtrl', function($scope, Restangular) {
$scope.people = Restangular.all('quotes.csv?s=MSFT+GE&f=nab').getList();
});
I'm confused by this error because since this is a public API and POSTMAN can access it, I'd assume that the header is already present in the API server. Why would I get this error when requesting from my local?
Any help would be GREATLY appreciated.
Here's me making a JSONP request which fails because it's trying to receive a CSV file. I don't think restangular knows how to read CSV files either which is what you are attempting. I think you need to do the same thing as you are now but using the YQL API instead because I don't think this is going to work.
Anyway here's the code:
http://plnkr.co/edit/GokYqzJ0dXw86C6AM2UP?p=preview
The request (which goes through but fails due to the file type):
app.controller('MainCtrl', function($scope, $http) {
$scope.name = 'World';
$http.jsonp('http://finance.yahoo.com/d/quotes.csv', {
params: {
callback: 'JSON_CALLBACK',
s: 'MSFT GE',
f: 'nab'
}
}).success(function(response) {
console.log(response);
}).catch(function(response) {
console.log(response);
})
});

Can't perform CORS request using Angularjs

I am writing my first AngularJS app and have run into a problem with CORS in Angular. Have tried what was mentioned in this reply but still have no luck solving this.
The JS code (main.js) is as follows:
var app = angular.module("app",[]);
app.config(['$httpProvider', function($httpProvider) {
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
app.controller("AppCtrl", function ($scope, $http) {
var postData = "username=demo&password=demo";
$http.post("http://sampleurl.com/login",postData).success(function(data, status, headers, config)
{
console.log(data);
});
});
The Index.html file is:
<!DOCTYPE html>
<html>
<head>
<title>Sample Angular App</title>
</head>
<body ng-app="app" ng-controller="AppCtrl as app">
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
<script src="main.js"></script>
</body>
</html>
The error I get is the following:
Failed to load resource: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I have tried running this request using Ajax and it works just fine with Ajax. For some reason can't get this to work using Angular. Any idea as to what I am doing wrong here?
Thanks!
Ok. So basically after alot of tinkering around I realised that params were not getting passed using
$http.post("http://sampleurl.com/login",postData)
So I rewrote this request as follows:
$http({
url:'http://sampleurl.com/api',
method:"POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: postData
})
This got the request to go through just fine. Hope this is of help to someone else.
Cheers!
There are two things you will need to do, in the .config you need to put this:
$httpProvider.defaults.withCredentials = true;
And then on your server you need to return an an Access-Control-Allow-Origin header, it would possibly look like this:
Access-Control-Allow-Origin:http://URL_OF_SITE_YOUR_ANGULARJS_APP_IS_AT
If you want to send a CORS request 'withCredentials', you'll need to have your server reply with 'Access-Control-Allow-Origin':'http(s)://your.request.origin'. A wildcard (*) reply will be refused by most browsers for requests with credentials.
I was stuck with the same issue, then I read from this link:
http://better-inter.net/enabling-cors-in-angular-js/
and things worked like a charm :)
var myApp = angular.module('myApp', [
'myAppApiService']);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
I had the same problem before and I resolve it by adding this header:
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},

Resources