Nodejitsu

Save time managing and deploying your node.js app. Code faster with jitsu and npm

create node.js web-services in one line

About the author

Name
Location
Worldwide
nodejitsu nodejitsu

UPDATE: Due to high demand, webservice.js is now under active development. You should also visit the Github to get the latest documentation code

Creating easy to consume web-services is a common problem in modern day computer science. Many web developers have had some experience either creating a web-service or building a client to consume a web-service (such as the Twitter API).

Using a node.js router like Journey, we can easily define maps for a basic JSON web-service. We can hard-code a few routes, assign each one a different request handler, and then write integration tests between our new Journey router and our business logic. The problem with this approach, is that it requires writing a lot of code, which requires a lot of development time.

If we enforce some very reasonable conventions and draw on a concept from Coldfusion, we can start creating robust web-services with one line of code.

Coldfusion?!?!

Yes, sigh Coldfusion. Before my days as a JavaScript developer I spent a lot of time in this wonderfully simple scripting language for the JVM, called Coldfusion. Coldfusion had "Coldfusion Components", or CFCs. A CFC was a simple way to encapsulate methods into an object. One of the more interesting properties of a CFC was it's ability to expose methods inside any CFC as "remote". This would allow the CFC method to be viewed directly over HTTP as a web-service. CFC's were exposed with nice auto-generate documentation and could work using multiple formats like XML, JSON, and WDDX.


Bringing the old and busted into the node and js

Building on the idea of exposing objects as turn-key web-services...

We make the following assumptions...

  • every node.js module has a name
  • node.js modules export methods
  • exported methods take an options hash as the first argument
  • exported methods take a callback as the last argument

Based on these assumptions, we can start turning node.js modules into web-services in seconds.


webservice.js

webservice.js is a node.js module that creates RESTFul web-services based on other node.js modules.

First, install webservice.js from npm.

 npm install webservice

Creating a web-service is very simple. In a previous version of this article, I showed how to expose the native fs module as an unprotected web-service. It was a neat proof of concept, but I've taken it down since no one should actually directly expose any of the native node modules.



Instead, here is a server that uses a demo module:

var webservice = require('./lib/webservice'),  
    demoModule = require('./examples/demoModule');

webservice.createServer(demoModule).listen(8080);  
console.log(' > json webservice started on port 8080');  

Now that we have created a basic web-service, let's start it up.

 node server.js 

Now there is a web-service running on port 8080. One of the nice things webservice.js does for you, is create its own documentation.

If we go to: http://localhost:8080/docs, we will see a description of our web-service

Another great feature is that we can return any documentation page as JSON by appending .json to the end of the request.

If we visit http://localhost:8080/docs.json we will see a listing of all our web-service methods as JSON (photo cropped).


Invoking web-service methods

Now that our web-service is running and we have an idea of how it's structured, we can invoke a simple method that will echo a msg.

curl -X GET http://localhost:8080/echo?msg=hello

Since HTTP verbs are relaxed, we can also do this:

curl -X POST -d "msg=hello" http://localhost:8080/echo



creating custom web-services

Creating custom web-services is very simple. There is more documentation available on github, but the basic design strategy is as follows:

// demo module
this.title = "Welcome to your webservice!";  
this.name = "demo api module";  
this.version = "0.1.0";  
this.endpoint = "http://localhost:8080";

exports.echo = function(options, callback){  
  callback(null, options.msg);
};
exports.echo.description = "this is the echo method, it echos back your msg";  
exports.echo.schema = {  
  msg: { 
    type: 'string',
    optional: false 
  }
};

exports.ping = function(options, callback){  
  setTimeout(function(){
    callback(null, 'pong');
  }, 2000);
}
exports.ping.description = "this is the ping method, it pongs back after a 2 second delay";  

Now we make a simple server file that will create the web-service for our custom module. Notice I left in the FS module. This is to illustrate how to use multiple modules in one web-service. You can specify as many modules as you'd like, granted they all have unique labels.

var webservice = require('./lib/webservice'),  
    demoModule = require('./examples/demoModule');

webservice.createServer(demoModule).listen(8080);  
console.log(' > json webservice started on port 8080');  

and to invoke methods over HTTP...

 curl http://localhost:8080/demo/echo/hello
 "hello"

 curl http://localhost:8080/demo/ping/async
 (waits 3 seconds)
 "pong"

summary

There are a lot of interesting options to explore when building node.js services. Having the ability to seamlessly expose modules as web-services seems like a powerful concept and I look forward to trying to build on it in the future. pull requests are always welcome.

* ninja out! *