Search code examples
javascriptangularjsngresource

ngResource transformResponse how to handle both error and normal data


My API implemented with expressJS returns json as normal response, but when an error occurred, returns error code with a plain text, by simply calling res.sendStatus(401).

This causes a problem on my frontend, I use angular ngResoruce, and the resource code is like this:

svc.authenticateApi = function() {
            return $resource(apiEndpoint + 'authenticate', null, {
                'save': {
                    method: 'POST',
                    transformResponse: function (data, header) {
                        console.log("transformResponse, header:", header());
                        console.log("transformResponse, data:", data);

                        return { data: angular.fromJson(data) };
                    },
                },
            });
        };

This works fine when normal JSON data is returned, however, when error status is returned, the data parameter is not a serialised JSON string, it's plain text, and I get errors like this:

enter image description here

Apparently transformResponse tries to parse text Unauthorised as JSON and failed. I can work around this by sending every error response as JSON on the server end by calling something like `res.status(401).send({error: "Unauthorised"}, but that feels like a hack, and I don't want to manually repeat error text for each status code.

Is there a better way to handle this? I don't want it sounds like a rant, but ngResource document is really poor and I start to think using $http is a much better solution.


Solution

  • I've moved away from $resource and am using $http everywhere. I just find everything about $resource to be a bit wonky. I do think returning JSON from the server in all scenarios sounds like the best approach though. You could implement a custom handler to test your incoming responses to work around this, but that doesn't really feel right to me.

    I'd guess that the error is occurring on the return { data: angular.fromJson(data) }; line though. You could wrap this in a try/catch as well.