Shoutout to Andy Joslin for the brilliant idea of wrapping resource actions. The service for the resource now appears as follows:
.factory('Todo', ['$resource', 'TokenHandler', function($resource, tokenHandler) {
var resource = $resource('http://localhost:port/todos/:id', {
port:":3001",
id:'@id'
}, {
update: {method: 'PUT'}
});
resource = tokenHandler.wrapActions( resource, ["query", "update"] );
return resource;
}])
The initial definition of the resource remains conventional. In this instance, a custom action named update
is included. Subsequently, the resource is replaced by the result of the tokenHandler.wrapAction()
method, which accepts the resource and an array of actions as arguments.
Essentially, the latter method modifies the actions to incorporate the authentication token in each request before returning an altered resource. Let's delve into the code for that:
.factory('TokenHandler', function() {
var tokenHandler = {};
var token = "none";
tokenHandler.set = function( newToken ) {
token = newToken;
};
tokenHandler.get = function() {
return token;
};
// wrap given actions of a resource to send auth token with every
// request
tokenHandler.wrapActions = function( resource, actions ) {
// duplicate original resource
var wrappedResource = resource;
for (var i=0; i < actions.length; i++) {
tokenWrapper( wrappedResource, actions[i] );
};
// return modified copy of resource
return wrappedResource;
};
// wraps resource action to send request with auth token
var tokenWrapper = function( resource, action ) {
// duplicate original action
resource['_' + action] = resource[action];
// create new action wrapping the original and sending token
resource[action] = function( data, success, error){
return resource['_' + action](
angular.extend({}, data || {}, {access_token: tokenHandler.get()}),
success,
error
);
};
};
return tokenHandler;
});
In the wrapActions()
method, a duplicate of the resource is generated from its parameters, and the actions
array is iterated over to invoke another function called tokenWrapper()
for each action. Finally, the modified copy of the resource is returned.
The tokenWrapper()
function initially duplicates the existing resource action with an appended underscore. Hence, query()
becomes _query()
. Subsequently, a new method supersedes the original query()
action, effectively wrapping it as suggested by Andy Joslin to include the authorization token with every request made through that action.
This approach allows us to leverage the predefined actions that accompany every AngularJS resource (such as get, query, save, etc.) without the need for redefining them. Additionally, in other parts of the code (like controllers), we can utilize the default action names seamlessly.