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.