11

I'm running a $http.get for a JSON and am getting a status of 0. I've downloaded the same JSON and the get works locally, and in Python using the requests library I can get the JSON no problem, but in AngularJS it's not working. What I don't understand is why angular isn't getting it but everything else is. Code snippet below.

function AgentListCtrl($scope, $http) {
  $http.get('http://foo.bar/api/objects').success(function(data) {
  $scope.objects = data;
}).error(function(data, status) {
  $scope.status1 = status;
});

This provides the JSON and parses it when using a local file, but otherwise it fails and sets status1 to 0.

sideshowbarker
  • 62,215
  • 21
  • 143
  • 153
Corbin Lewis
  • 370
  • 3
  • 5
  • 14

3 Answers3

21

Just to make this clear since is not directly stated in the above answer (but in its comments) and, like me, some Angular newbies may be spending some time on this:

  • Angular's $resource will be able to execute a REST verb on another server, which in turn will respond correctly (with a status 200). Angular will nevertheless fail with a cryptical message, identifyiable by the status 0. It is further misleading since, in a browser's debugger, you may actually see the server's answer.

  • Angular will do an OPTIONS request on a cross-domain request (at least for the default query() method) unless specified on the contrary. Usually the server will not answer with the desired content (i.e. your representation). One simple way of doing this per request is specifying the method to be 'GET'.

    $resource('http://yourserver/yourentity/:id', {}, {query: {method: 'GET'});
    
  • The server answering your REST requests MUST include the headers specified by CORS [1] 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. This value may be *.

Complementing this answer for anyone integrating AngularJS with spring-data-rest-webmvc:

  • the HATEOAS json formatted response will not be properly consumed by Angular, producing instead the error Expected response to contain an array but got an object. This is solved by adding the isArray: false parameter to the $resouce's configuration;

  • a very to-the-point example of configuring CORS for the spring-data-rest-webmvc scenario is presented at [2] (see the SimpleCORSFilter)

[1] https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS

[2] https://spring.io/guides/gs/rest-service-cors/

h7r
  • 4,196
  • 2
  • 22
  • 30
  • 3
    Note that Angular does not make the OPTIONS/preflight request itself. The browser does. In fact, Angular has no knowledge of this request, it is completely transparent to client-side code. – Ray Nicholus Feb 25 '14 at 18:13
  • @ray-nicholus Interesting. Can you point to any references on this? – h7r Feb 26 '14 at 08:18
  • This is a basic concept of CORS. You read about CORS in many places, such as the [CORS spec](http://www.w3.org/TR/cors/) or [this MDN article](https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS) – Ray Nicholus Feb 26 '14 at 15:21
  • For me, the thing that worked (or provided a catalyst when speaking with our API developer) was that the CORS headers were missing. All the requests that worked had these headers, his non working one (browser said 404, angular said 0) did not have these headers present. Thanks! – coblr Jul 20 '15 at 23:23
  • As a specific for aside, I ran into this issue today when building an app with ionic/angular and a laravel backend for iOS9. The problem was twofold with apples transport layer security. The link below and the answer above helped me out http://stackoverflow.com/questions/31254725/transport-security-has-blocked-a-cleartext-http – Jonny C Sep 23 '15 at 17:04
2

In your code, the status assignment only occurs when the error happens. You should be able to get the status when the call was made successfully like this:

success(function(data, status, headers, config) {
    $scope.objects = data;
    $scope.status1 = status;
}).error(function(data, status) {
    $scope.status1 = status;
});
zs2020
  • 52,221
  • 27
  • 148
  • 209
  • But it's still raising an error and not actually getting the content when it's pulling it from the server when it did get the identical json from local just fine. I guess the status 0 code isn't as important as I thought, it's really the failure to get the json. – Corbin Lewis Jul 29 '13 at 17:40
  • 1
    pulling it from the server? Make sure you are not calling an API hosted on another domain. Since javascript doesn't allow cross domain API call by default. – zs2020 Jul 29 '13 at 17:44
  • That sounds like exactly what's happening. Thank you. I'll work with the local file until I push it to the server. – Corbin Lewis Jul 29 '13 at 17:48
  • No problem. If you are interested in how to make the cross-domain call work, you can check this [thread](http://stackoverflow.com/questions/12111936/angularjs-performs-an-options-http-request-for-a-cross-origin-resource) – zs2020 Jul 29 '13 at 17:51
  • I have exact same problem. But I tried pulling data from w3schools test url given here. http://www.w3schools.com/angular/angular_http.asp this http://www.w3schools.com/angular/angular_http.asp service url load the data for my local angular app. seems angular allows cross domain api call by now. what would be my problem ? – amilaishere Aug 20 '15 at 08:05
1

I was having a similar problem myself. A third party API that returns JSON just fine through every other means was failing with status 0 when called through Angular's $http.get() method.

In my case there wasn't any CORS problem. Instead, the URL I was using for the API was not quite right and the server was issuing a 301 response. Angular wasn't respecting the redirect.

Word to the wise.