Getting error when trying get JSON from remote url - angularjs

I'm trying load this json file from remote url. In the beginning I was using $http.get function, but I was getting the next error message:
CORS 'Access-Control-Allow-Origin'
Now I am using JSONP, but nothing happens.
service.js file:
angular.module("elcomaApp").factory('ElcomaService', ['$http', function($http){
return $http({
method: 'JSONP',
url: 'http://vagalumewifi.com.br/timeline.json'
}).success(function(response){
return response.data;
}).error(function(err){
return err;
});
}]);
controller.js file:
angular.module("elcomaApp", []).controller('MainController', ['$scope', 'ElcomaService', function($scope, ElcomaService){
$scope.name = 'Natanael Santos';
console.log($scope.name);
ElcomaService.success(function(data){
$scope.elcomaData = JSON.parse(data);
var i = 0;
for (x in $scope.elcomaData){
console.log(i);
i++;
console.log(x.date);
}
}).error(function(data){
console.log(data);
});
}]);
app.js file:
var app = angular.module("elcomaApp", ['ngMaterial', 'ngRoute']);
I already hava read a lot of articles on stackoverflow, but no one work for me.

I'd suggest using $http.jsonp(url) method:
angular.module("elcomaApp").factory('ElcomaService', ['$http', function($http) {
$http.jsonp('http://vagalumewifi.com.br/timeline.json')
.success(function(data) {
console.log(data); // you can't `return` here...
}).error(function(err){
console.err(err);
});
}]);
Note: be warned that you can't expect that return in an async method has the same behavior as in a sync environment... :-)

Your original error is your clue. The endpoint server won't allow access from another domain.
CORS: Cross Origin Requests
You need to allow access on the endpoint server for the type of HTTP method you want to use (i.e. GET, POST, HEAD, ...) Additionally depending on what you're doing you may need to allow for an OPTIONS request, see Preflighted Requests in the MDN documentation above.
If you don't have access to that server you may need to do a work around by making $http call a script on your server that will fetch the file for you. I've done this before using PHP as a proxy and using PHP's file_get_contents function to grab files from other servers of a different domain.

Related

Trouble understanding how angularjs $httpDefaultCache, $cacheFactory and how to access that data

I'm having to inline all resources into one file and this includes all the data that my application uses. With a gulp process, I've been able to create a $cacheFactory with all the data:
angular.module('app').run('$cacheFactory', '$http', function($cacheFactory, $http){
var $httpDefaultCache = $cacheFactory.get('$http');
$httpDefaultCache.put('/data/names.json',{...});
$httpDefaultCache.put('/data/places.json',{...});
});
My understanding of how to access this instead of making a call externally (file) may be incorrect.
I thought that by setting $httpProvider.defaults.cache = true, that my request to the endpoints of above would use the default cache.
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.cache = true;
}]);
Instead I get an error of
https://.../data/names.json 404 (Not Found)
As if it is looking within the the client and not in angular's cache. The type is also an xhr.
data.load(names, '/data/names.json');
...
function load(broadcastName, url, force){
if(!isLoaded[broadcastName] && !force){
console.log('Loading name data from', url);
// Make the http GET request
http({
method: 'GET',
url: url,
cache: true
}).then(function success(response){
console.log("response: ", response)
...
})
Had to create a custom http request that perfectly imitates angular $http service. It is used in several other applications we have, so I know it works. Only thing that has been added for this implenation is cache:true.
I've looked at several other questions that were similar, but I am still not understanding how it is working. How does using http default cache work? And is there something I should be aware of that I may be glossing over?
I hope this makes sense.
There's no special term for $http cache like '$httpDefaultCache'. It works like you expect it to work. You set either $httpProvider.defaults.cache or cache request option to true, and the response is retrieved from $http cache, which is available by default as $cacheFactory.get('$http').
Cache is just key/value storage. If request URL doesn't match a key completely, cache won't be used.
Here's an example how it works:
$cacheFactory.get('$http').put('/foo', 'foo');
$http({ url: '/foo', cache: true })
.then(result => {
$scope.foo = result.data;
})
.catch(result => console.error(result))

API-key header is not sent (or recognized). Angularjs

I'm trying to access an API with AngularJS but I get the following error:
XMLHttpRequest cannot load http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://purepremier.com' is therefore not allowed access.
This is my code for the service:
angular.module('PremierLeagueApp.services', []).
factory('footballdataAPIservice', function($http) {
var footballdataAPI = {};
footballdataAPI.getTeams = function() {
$http.defaults.headers.common['Auth-Token'] = 'token';
return $http.get('http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK');
};
return footballdataAPI;
});
I use an authentication token (api key) to access the api, but according the API owner this API key header is not sent or recognized. Do you have any idea how I can adapt the code to make this work? thanks!
You should hide that API key before posting on a public site such as this. I would advise you regenerate your key (if possible) just in case - better safe than sorry.
Assuming your site url is 'http://purepremier.com' from the error message, the API should add a 'Access-Control-Allow-Origin' header with your site URL to allow you access. Have a look here for more information.
This is not directly related to your problem, but I notice you are setting $http defaults every time getTeams() is called. You should either set this outside of the actual function call (preferably in a run block), or just send the GET request with that header specifically applied. As the API key is specific (I assume) to that call, you may not want to be sending it to anyone and everyone, every time you make a HTTP request.
Change your factory code like this:
factory('footballdataAPIservice', function($http) {
return {
getTeams: function(){
return $http({
url:'http://www.football-data.org/alpha/soccerseasons/398/leagueTable',
headers: { 'X-Auth-Token': 'your_token' },
method: 'GET'
}).success(function(data){
return data;
});
}
}
});
Inject factory in your controller and retreive the data:
.controller('someController',function(footballdataAPIservice,$scope){
footballdataAPIservice.getTeams().then(function(data){
$scope.teams=data;
console.log($scope.teams)
});
});
Here is the working plunker
You change the Auth-Token To Authorization
$http.defaults.headers.common['Authorization'] = 'token';
Because token is send via headers using Authorization
try jsonp
angular.module('PremierLeagueApp.services', []).
factory('footballdataAPIservice', function($http) {
var footballdataAPI = {};
footballdataAPI.getTeams = function() {
$http.defaults.headers.common['Auth-Token'] = 'token';
return $http.jsonp('http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK');
};
return footballdataAPI;
});

Angular $http request issue

i am trying to retreive some images from a flickr service this one.
Unfortunately, i have the following error:
XMLHttpRequest cannot load http://api.flickr.com/services/feeds/photos_public.gne?format=json.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3000' is therefore not allowed access.
Here's my code:
angular.module('myApp')
.service('getFlickrImages', function($http){
this.getData = function() {
delete $http.defaults.headers.common['X-Requested-With'];
return $http({
method: 'GET',
url: 'http://api.flickr.com/services/feeds/photos_public.gne?format=json'
});
}
});
angular.module('myApp')
.controller('MainCtrl', function ($scope, getFlickrImages) {
$scope.data = null;
getFlickrImages.getData().then(function(dataResponse) {
$scope.data = dataResponse;
});
});
Here's a Plunker if someone can help me
I finally found that chrome plugin:
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?utm_source=chrome-ntp-icon
Install it, activate it and refresh the view.
It will a least let you work without that Access-Control-Allow-Origin issue.
It would be good if someone bring the fix but directly in the code...

Access Control Allow Origin | AngularJS

I was integrating the flickr app into my app.
I am receiving the error below:
XMLHttpRequest cannot load https://api/flickr.com/services/rest?api_key=4cd95b5ad05844319ee958bf96ec0150&format=json&method=flickr.photos.search&nojsoncallback=1. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://sinch12j12.ads.autodesk.com' is therefore not allowed access. The response had HTTP status code 400.
Below is the client side code:
(function() {
'use strict';
angular.module('flickrApp', ['ngMaterial'])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}])
.controller('ListController', ['$scope', '$http', function($scope, $http) {
$scope.results = [];
$scope.search = function() {
$http({
method: 'GET',
url: 'https://api/flickr.com/services/rest',
params: {
method: 'flickr.photos.search',
api_key: '4cd95b5ad05844319ee958bf96ec0150',
text: $scope.searchTerm,
format: 'json',
nojsoncallback: 1
}
}).success(function(data) {
$scope.results = data;
}).error(function(error) {
console.log(error);
});
}
}]);
})();
Please let me know how shall it may be resolved ?
You are trying to make AJAX requests to a different server (domain), that does not allow ajax requests from other domains. There are 2 solutions to your problem :
Edit the configurations of the remote server (Allow-Origin header) to allow AJAX requests from other servers. I think this solutions is not feasible in your case, as you are not capable of configuring the flickr server
Create a proxy server component in your server, exposing an API to your application. Thus, you will make the AJAX requests to your API (and since it is the same domain, you will not have a cross-domain request issue), and your server will make the requests to the flickr API and respond in your AJAX call.
You're trying to use AJAX to retrieve some data from a remote server (in this case, the Flickr server). For security reasons, AJAX calls to any file on a remote server is not permitted unless that file has allowed AJAX calls from remote servers. Here, the Flickr file your trying to get doesn't allow AJAX calls from any other servers, that's why you won't be able to access the data in that file.
Thanks and let me know if you have any more problems.

angular-http-auth with $http transformResponse

I'm using angular-http-auth to show a login dialog whenever a 401 "unauthorized" response is returned from the server.
Since I'm cool, I also try to deserialize response objects in my services. For example, if a service requests a car and the response is {make: Honda, model: Civic}, I try to deserialize that into a Car object using transformResponse.
For example:
getCar: function() {
return $http.get('/api/car', {
method: 'GET',
transformResponse: function(data, headers) {
var c = angular.fromJson(data);
return new Car(c);
}
});
}
This doesn't work with angular-http-auth. If the response was a 401 Unauthorized, you'll get a javascript error. It's because angular will try to run that transformResponse code even if the response was a 401.
It turns out that $http interceptors (which is what angular-http-auth uses) are run AFTER the transformResponse code. That's a huge problem, because none of that code in transformResponse will work if the server response was a 401 (there wouldn't be any data)
Is this a problem for anyone else? How did you get around it? Am I not to use transformResponse if I use $http interceptors?
Late to the party, I know, but to anyone coming here from Google like I did (I also posted this as a comment on a related issue filed with the Angular repo):
I also found it to be confusing that response interceptors run after the transformResponse method. I added a method to $http.defaults.transformResponse. Here is an example from the documentation on how to do that.
So, if you need to basically have a response interceptor that runs before the transformResponse method, this should do it:
'use strict';
angular.module('app')
.run(function ($http) {
$http.defaults.transformResponse.push(function (data, headers) {
// do stuff here before the response transformation
// Be sure to return `data` so that the next function in the queue can use it.
// Your services won't load otherwise!
return data;
});
});
If your services or http calls don't have their own response transformer, you're good now.
If your services do have their own transformResponse method, they will actually override all default transformers (I found this out after a long read of the documentation), and the above code will not run.
To circumvent this, you can follow this example in the docs.
To get around this problem I don't use transformResponse anymore. I just can't see the point of transformResponse if it runs before $http interceptors.
In order to use angular-http-auth and also deserialize responses in your services, you can write your services so that they execute the HTTP request first and then deserialize the response in a callback function.
As an example, here is how I would have restructured the example in the OP:
Plunker
services.factory('HttpCarService', function($resource, $q) {
var resource = $resource('/api/car');
return {
getCar: function() {
var deferred = $q.defer();
var car = null;
var successCallback = function(data, status, headers, config) {
var c = angular.fromJson(data);
car = new Car(c);
deferred.resolve(car);
};
var errorCallback = function(data, status, headers, config) {
deferred.reject("something wrong");
};
var result = resource.get(successCallback, errorCallback);
return deferred.promise;
}
};
});
This pattern will also work if data is an array.
$http interceptors will run before either of the callback methods are executed. If your $resource needs url params, you can make the getCar() function accept a config object as a parameter, and pass the necessary information on when you make the $resource.get() call.

Resources