Pregunta

I have a service available on a server distinct from my grunt server, which serves my angularjs app.
The external server is an Apache server, serving JSON data with PHP. I would like to intercept any possible server error (from "server down", to "404"...).

I have tried to use interceptors, this way:

app.factory('myFactory', function($resource) {
  return $resource('http://www.remote.server.com/api/WRONGPATH',
});

app.config(function ($routeProvider, $httpProvider) {

  ...

  $httpProvider.responseInterceptors.push(function($q) {
    return function(promise) {
      return promise.then(function(successResponse) {
        if (successResponse.config.method.toUpperCase() !== 'GET') {
          console.info('success');
        }
        return successResponse;
      }, function(errorResponse) {
        switch (errorResponse.status) {
          case 401:
            console.info('wrong usename or password');
            break;
          case 403:
            console.info('no rights to do this');
            break;
          case 500:
            console.info('server internal error: ' + errorResponse.data);
            break;
          default:
            console.info('error ' + errorResponse.status + ': ' + errorResponse.data);
        }
        return $q.reject(errorResponse);
      });
    };
  });

});

with no success: I always fall in the 'default' switch case, with errorResponse.status == 0.
I suppose this happens because the browsers stop when intercepting a CORS error...
Everything works just fine if I change the remote url with a local one...

Is there any possibility to handle angular.js $resource (or $http) remote requests errors?

I would also accept a design shift suggestion, like reimplementing my PHP service in a grunt-like way... (my PHP service - actually - just prints a JSON list of image names from a server folder...).

¿Fue útil?

Solución

I believe you're pushing your interceptor to the wrong place. The $http docs indicate that you should be pushing onto:

$httpProvider.interceptors

rather than:

// I can only find references to this on old tutorials, so maybe it's been deprecated
$httpProvider.responseInterceptors 

So you'd have something like:

$httpProvider.interceptors.push(function($q) {
  return {
    'response': function(response) {
      if (successResponse.config.method.toUpperCase() !== 'GET') {
        console.info('success');
      }
      return response || $q.when(response);
    },
    'responseError': function(response) {
       switch (response.status) {
        case 401:
          console.info('wrong usename or password');
          break;
        case 403:
          console.info('no rights to do this');
          break;
        case 500:
          console.info('server internal error: ' + response.data);
          break;
        default:
          console.info('error ' + response.status + ': ' + response.data);
      }

      return $q.reject(response);
    }
  };
});

working plnkr: here

Otros consejos

From my understanding this is an issue relating to CSRF/XSRF protection, rather than AngularJS. You will get the same issue in other frameworks or poj. In PHP you will need to enable CORS if you are accessing your content across domain and will need to specify the servers that require access or open it up.

http://www.w3.org/wiki/CORS_Enabled http://enable-cors.org/server_php.html

Essentially AngularJS is constrained to the response provided by the browser, which is in turn constraining the response since the request is unauthorised due to XSRF protection. Also, regarding AngularJS and XSRF, it will read the token session cookie (provided by the server) and place it into the HTTP header in subsequent requests, which then is up to the server to decide whether or not it will accept it.

https://docs.angularjs.org/api/ng/service/$http

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top