Last active
October 6, 2015 01:20
-
-
Save masimplo/324e77a2dd20fb4aa227 to your computer and use it in GitHub Desktop.
Decorating $http service to support url interpolation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function httpDecorator($delegate: ng.IHttpService) { | |
var $http = $delegate; | |
var wrapper = () => { | |
// interpolate the url | |
var config = arguments[0]; | |
config.url = interpolateUrl(config.url, config.params, config.data); | |
return $http.apply($http, arguments); | |
}; | |
// $http has convenience methods such as $http.get() that we have | |
// to pass through as well. | |
Object.keys($http).filter(key => (typeof $http[key] === 'function')).forEach(key => { | |
wrapper[key] = () => { | |
// interpolate the url | |
arguments[0] = interpolateUrl(arguments[0], arguments[1].params, arguments[1].data); | |
return $http[key].apply($http, arguments); | |
}; | |
}); | |
// the $http service also has object properties that need to be copied (eg. defaults) | |
Object.keys($http).filter(key => (typeof $http[key] === 'object')).forEach(key => { | |
wrapper[key] = $http[key]; | |
}); | |
return wrapper; | |
} | |
httpDecorator.$inject = ['$delegate']; | |
// register the decorator on the loaded module | |
mainModule.config([ | |
'$provide', $provide => { | |
$provide.decorator('$http', httpDecorator); | |
} | |
]); | |
// Code beyond this point adapted from: https://gist.github.com/bennadel/11178024/ | |
// I move values from the params and data arguments into the URL where | |
// there is a match for labels. When the match occurs, the key-value | |
// pairs are removed from the parent object and merged into the string | |
// value of the URL. | |
function interpolateUrl(url, params, data) { | |
// Make sure we have an object to work with - makes the rest of the | |
// logic easier. | |
params = (params || {}); | |
data = (data || {}); | |
// Strip out the delimiter fluff that is only there for readability | |
// of the optional label paths. | |
url = url.replace(/(\(\s*|\s*\)|\s*\|\s*)/g, ""); | |
// Replace each label in the URL (ex, :userID). | |
url = url.replace( | |
/:([a-z]\w*)/gi, | |
($0, label) => { | |
// NOTE: Giving "data" precedence over "params". | |
var val = popFirstKey(data, params, label); | |
return val !== null && val !== undefined ? val : ''; | |
} | |
); | |
// Strip out any repeating slashes (but NOT the http:// version). | |
url = url.replace(/(^|[^:])[\/]{2,}/g, "$1/"); | |
// Strip out any trailing slash. | |
url = url.replace(/\/+$/i, ""); | |
return (url); | |
} | |
// I take 1..N objects and a key and perform a popKey() action on the | |
// first object that contains the given key. If other objects in the list | |
// also have the key, they are ignored. | |
function popFirstKey(object1, object2, objectN) { | |
// Convert the arguments list into a true array so we can easily | |
// pluck values from either end. | |
var objects = Array.prototype.slice.call(arguments); | |
// The key will always be the last item in the argument collection. | |
var key = objects.pop(); | |
var object = null; | |
// Iterate over the arguments, looking for the first object that | |
// contains a reference to the given key. | |
while (object = objects.shift()) { | |
if (object.hasOwnProperty(key)) { | |
return (popKey(object, key)); | |
} | |
} | |
} | |
// I delete the key from the given object and return the value. | |
function popKey(object, key) { | |
var value = object[key]; | |
delete (object[key]); | |
return (value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment