Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created April 22, 2014 12:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bennadel/11178024 to your computer and use it in GitHub Desktop.
Save bennadel/11178024 to your computer and use it in GitHub Desktop.
Using URL Interpolation With $http In AngularJS
<!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>
@tommck
Copy link

tommck commented Jan 22, 2015

FYI: your interpolate doesn't handle protocol-relative URLs (e.g. "//foocdn.com/lalala.js"), it strips the leading "/"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment