Created
April 22, 2014 12:55
-
-
Save bennadel/11178024 to your computer and use it in GitHub Desktop.
Using URL Interpolation With $http In AngularJS
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
<!doctype html> | |
<html ng-app="Demo"> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
Using URL Interpolation With $http In AngularJS | |
</title> | |
</head> | |
<body ng-controller="DemoController"> | |
<h1> | |
Using URL Interpolation With $http In AngularJS | |
</h1> | |
<!-- Initialize scripts. --> | |
<script type="text/javascript" src="../../vendor/jquery/jquery-2.1.0.min.js"></script> | |
<script type="text/javascript" src="../../vendor/angularjs/angular-1.2.16.min.js"></script> | |
<script type="text/javascript"> | |
// Define the module for our AngularJS application. | |
var app = angular.module( "Demo", [] ); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// I control the main demo. | |
app.controller( | |
"DemoController", | |
function( $scope, httpi ) { | |
// NOTE: The (.|.) notation will be stripped out automatically; it's only | |
// here to improve readability of the "happy paths" of labels. The | |
// following urls are identical: | |
// -- | |
// api/friends/( :listCommand | :id/:itemCommand ) | |
// api/friends/:listCommand:id/:itemCommand | |
var url = "api/friends/( :listCommand | :id/:itemCommand )"; | |
console.warn( "None of the API enpoints exist - they will all throw 404." ); | |
// Clear list of friends - matching listCommand. | |
httpi({ | |
method: "post", | |
url: url, | |
data: { | |
listCommand: "reset" | |
} | |
}); | |
// Create a new friend - no matching URL parameters. | |
httpi({ | |
method: "post", | |
url: url, | |
data: { | |
name: "Tricia" | |
} | |
}); | |
// Get a given friend - ID matching. | |
httpi({ | |
method: "get", | |
url: url, | |
data: { | |
id: 4 | |
} | |
}); | |
// Make best friend - ID, itemCommand matching. | |
httpi({ | |
method: "post", | |
url: url, | |
data: { | |
id: 4, | |
itemCommand: "make-best-friend" | |
} | |
}); | |
// Get besties - no matching URL parameters. | |
httpi({ | |
method: "get", | |
url: url, | |
params: { | |
limit: "besties" | |
} | |
}); | |
} | |
); | |
// -------------------------------------------------- // | |
// -------------------------------------------------- // | |
// I provide a proxy for the $http service that interpolates the URL of the | |
// request before executing the underlying HTTP call. | |
// -- | |
// NOTE: The "i" stands for "interpolation". | |
app.service( | |
"httpi", | |
function( $http ) { | |
// Return the public API. | |
return( httpProxy ); | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
// I proxy the $http service and merge the params and data values into | |
// the URL before creating the underlying request. | |
function httpProxy( config ) { | |
config.url = interpolateUrl( config.url, config.params, config.data ); | |
return( $http( config ) ); | |
} | |
// --- | |
// PRIVATE METHODS. | |
// --- | |
// 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, | |
function( $0, label ) { | |
// NOTE: Giving "data" precedence over "params". | |
return( popFirstKey( data, params, label ) || "" ); | |
} | |
); | |
// 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, key ) { | |
// 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 ); | |
} | |
} | |
); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI: your interpolate doesn't handle protocol-relative URLs (e.g. "//foocdn.com/lalala.js"), it strips the leading "/"