Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Behaviour for resource with both transformResponse and interceptors #10324

Closed
ZNS opened this issue Dec 4, 2014 · 19 comments
Closed

Behaviour for resource with both transformResponse and interceptors #10324

ZNS opened this issue Dec 4, 2014 · 19 comments

Comments

@ZNS
Copy link

ZNS commented Dec 4, 2014

I have a $resource with both transformResponse and an interceptor. The transformResponse deserializes the response from json and then modifies it. The interceptor handles responseError. The problem is when the request throws http error 500 the transformresponse is called (where the status of the request is not available) it tries to deserialize json and fails. In the interceptor responseError method I now get an object that has a property "message" with "Json.Parse error". I am unable to catch the http 500 error anywhere.

@pkozlowski-opensource
Copy link
Member

@ZNS I think we've got already a similar issue for this. To confirm, could you please prepare a plunk with a minimal reproduce scenario?

@ZNS
Copy link
Author

ZNS commented Dec 4, 2014

Here it is. As you can see in responseError for the interceptor we don't get access to the request status or config, just a message. It is also not possible to figure out the http exception from the transformResponse method.
http://plnkr.co/edit/8M7LqOxZGaegjjzKnVqG?p=info

@caitp
Copy link
Contributor

caitp commented Dec 4, 2014

This is how promises work, @ZNS --- you have your promise handler, it throws, the chained promise is rejected with the exception that was thrown.

This is pretty much working as expected, so I'm not sure we want to do much about this. The weird thing to me, is that $resource is transforming your 404 response at all.

@ZNS
Copy link
Author

ZNS commented Dec 4, 2014

@caitp The issue is that if I use transformResponse the http exception is not caught in the interceptors responseError. Hence the only way to find out if an http exception was thrown is to parse the html output (if any) in transformResponse. This can't be how it's meant to be.

I don't see why transformResponse is called at all if there was an http exception (status != 200). I'd prefer that responseError on the interceptor caught the http exception.

@caitp
Copy link
Contributor

caitp commented Dec 4, 2014

I understand your issue.

This is how it's meant to be, because response interceptors happen after transformation occurs --- this allows them to catch errors during transformation.

It might be sensible to include an HTTP status in the transform functions, though.

@ZNS
Copy link
Author

ZNS commented Dec 4, 2014

Ok. What I want to do is to retry a request if there's an http exception. But that will not be possible if I attach transformResponse then? Because I can't find out if there was an http exception and even if I get the http status back I won't get the http config of the request to retry it?

By the way I think this is the similar issue for this:
#7594

@caitp
Copy link
Contributor

caitp commented Dec 4, 2014

I don't think it makes sense to send the config object to the transform function. but it may make sense to send the response object, or just the status code

@ZNS
Copy link
Author

ZNS commented Dec 4, 2014

As a workaround I guess I could skip transformResponse and use the response method on the interceptor instead. Since I'm only interested in manipulating the parsed json. However since I'm using ngResource I am attaching transformResponse only to certain resources. But I guess I can create multiple interceptors to get around that.

Anyway I think it'd be great to be able to handle http exceptions even when using tranformResponse.

@gkalpak
Copy link
Member

gkalpak commented Dec 5, 2014

An idea would be to follow the interceptors "paradigm" for transformers as well, i.e. having transformRequest, transformRequestError, transformResponse and transformResponseError.
But it is might be too big of a change for the value it adds.

Passing the status to the response transformer seems reasonable though (and is probably "good enough").

@pkozlowski-opensource
Copy link
Member

Yes, I think we had a request to include response status so transformers can inspect it.

@pkozlowski-opensource
Copy link
Member

Actually, thinking about this one some more - do we want to run response transforms for failed requests?

@ZNS
Copy link
Author

ZNS commented Dec 6, 2014

I would say that if the request didn't finish with a 200 OK, the transformResponse shouldn't be called. I can see no reason to transform for example a 404, 500, 403 or 401 result. If you want to handle these they should be caught using an interceptor.

@BBlackwo
Copy link
Contributor

BBlackwo commented Aug 8, 2016

As far as I can tell, this issue was never resolved. Are there any updates / workarounds for this?

@gkalpak
Copy link
Member

gkalpak commented Aug 8, 2016

This has been resolved with 1b74097. If you are facing a different problem, please open a new issue.

@BBlackwo
Copy link
Contributor

BBlackwo commented Aug 9, 2016

Great thanks @gkalpak! Looks like the documentation was never updated though.

@gkalpak
Copy link
Member

gkalpak commented Aug 9, 2016

I don't know what you would expect to have been updated in the $resource documentation (the change was made to $http, which $resource delegates to), but feel free to submit a pull request with any docs updates you see fit.

@BBlackwo
Copy link
Contributor

BBlackwo commented Aug 18, 2016

@gkalpak and @pkozlowski-opensource I submitted a PR to update the $resource docs here: #15041

@smart-dream
Copy link

@BBlackwo when I use transformResponse ,the http exception is not caught in the interceptors responseError.I should be how to solve this problem. currently ,I am special deal with status === 401 in transformResponse , but I think this is way too low .I would like to ask you how to solve this problem.thanks.

@BBlackwo
Copy link
Contributor

BBlackwo commented Sep 19, 2016

@smart-dream here is some sample code using transformResponse:

angular.module('myModule')
  .service('myService', ['$resource', 'myTransformer', function ($resource, myTransformer) {
       return $resource('https://mysite.com/some-endpoint/:someParam', {someParam: '@someParam'},
        {
          get: {
            method: 'GET',
            transformResponse: myTransformer.transformTheResponse
          }
        });
    }]
);

angular.module('myModule')
  .factory('myTransformer', [function () { 
    this.transformTheResponse = function (data, headers, status) {
      var myResponse, transformedData;
      var json = angular.fromJson(data);

      if (status === 401) {
        // Return a custom response...
        return myResponse;
      }

      // Do some transformation with data...
      return transformedData;
    };
  }]
);

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.