Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

httpi - A Lightweight $resource-Inspired Module For AngularJS

By Ben Nadel on

As I blogged about before, I'm not a huge fan of the $resource module in AngularJS. But, it does have some features that I do like; namely, URL interpolation and the encapsulation of URLs across requests to the same resource. I created the "httpi" module in an attempt to build these features on top of the $http service while still providing direct access to the flexibility of the $http service underneath.

View the httpi project on my GitHub account.

The httpi service is really just a preprocessor for the underlying $http service. It takes your configuration object, interpolates the URL (hence the "i" in "httpi"), and then passes the updated configuration object off to $http. It then returns the same promise that the $http service returned to it.

The httpi service can also create $resource-inspired objects that apply the same URL across different HTTP calls. But, like the httpi service, each HttpiResource instance method takes a normal configuration object, modifies it, and then passes it off to the underlying $http service.

NOTE: When I say "$resource-inspired," I do so very loosely. I do not mean to imply that I am recreating the $resource feature-set; rather, that I am extracting what I personally found useful in the $resource-oriented approach.

To see this in action, take a look at the code below (which is the example on my GitHub project page). I'm creating an httpi resource and then invoking several of the convenience methods:

<!doctype html>
<html ng-app="Demo">
<head>
	<meta charset="utf-8" />

	<title>
		Using The httpi Service To Make AJAX Requests In AngularJS
	</title>

</head>
<body ng-controller="DemoController">

	<h1>
		Using The httpi Service To Make AJAX Requests In AngularJS
	</h1>


	<!-- Initialize scripts. -->
	<script type="text/javascript" src="vendor/angular-1.2.16.min.js"></script>
	<script type="text/javascript" src="../lib/httpi.js"></script>
	<script type="text/javascript">

		// Define the module for our AngularJS application.
		var app = angular.module( "Demo", [ "httpi" ] );


		// -------------------------------------------------- //
		// -------------------------------------------------- //


		// I control the main demo.
		app.controller(
			"DemoController",
			function( $scope, httpi ) {

				console.warn( "None of the API endpoints exist - they will all throw 404." );

				// NOTE: The (.|.) notation will be stripped out automatically; it's only
				// here to improve readability of the "happy paths" for interpolation
				// labels. The following urls are pre-processed to be identical:
				// --
				// api/friends/( :listCommand | :id/:itemCommand )
				// api/friends/:listCommand:id/:itemCommand
				var resource = httpi.resource( "api/friends/( :listCommand | :id/:itemCommand )" );

				// Clear list of friends - matching listCommand.
				resource.post({
					data: {
						listCommand: "reset"
					}
				});

				// Create a new friend - no matching URL parameters.
				resource.post({
					data: {
						name: "Tricia"
					}
				});

				// Get a given friend - ID matching.
				resource.get({
					data: {
						id: 4
					}
				});

				// Make best friend - ID, itemCommand matching.
				resource.post({
					data: {
						id: 4,
						itemCommand: "make-best-friend"
					}
				});

				// Get gets friends - no matching URL parameters.
				resource.get({
					params: {
						limit: "besties"
					}
				});

				// Get a friend as a JSONP request.
				// --
				// NOTE: The "resource" will auto-inject the "JSON_CALLBACK" marker that
				// AngularJS will automatically replace with an internal callback name.
				resource.jsonp({
					data: {
						id: 43
					}
				});

			}
		);

	</script>

</body>
</html>

Notice that the configuration objects passed into the "resource" methods don't have to include the Method or URL properties - these are automatically interpolated and injected into the configuration object before they are passed-off to the underlying $http service.

When we run the above code, we get the following network activity:

POST /api/friends/reset
POST /api/friends
GET /api/friends/4
POST /api/friends/4/make-best-friend
GET /api/friends?limit=besties
GET /api/friends/43?callback=angular.callbacks._0

Of course, you don't have to use the resource part of the module; the resource is kind of like a preprocessor for the httpi service which is, itself, a preprocessor for the $http service. If you call the httpi service directly, you'll still get the URL interpolation - you simply have to pass-in the URL with each request.

Obviously, the value of this module is heavily colored by my own experience with the $resource module in AngularJS. If you're loving $resource, I am not suggesting that you stop using it. But, for me personally, it wasn't a huge value-add. So, I tried to take the parts that I did like and rebuild them on top of the $http service in a very transparent way.



Reader Comments

Couldn't this be written into a decorator in order to avoid having to inject the wrapping service instead of the original $http?

@Michael,

You probably could. I'm only recently learning about decorators; so, at the time I wrote this, it wasn't an option for me personally.

@Michael,

I tried to take a look in your implementation as decorator but the link is dead, perhaps you can update it. Thanks !