home nodejitsu.com

about the author

Name:
Marak Squires
Github:
marak
Twitter:
marak
Location:
New York, NY

about this article

Date Released:
Friday, Sep 24 2010
Code Examples:
  • server2.js

also by this author

  • hiring open source developers
  • fault tolerant applications in nodejs
  • package json cheat sheet
  • npm cheatsheet
  • spawning hookio hooks
  • using nodejitsu for nko
  • getting refunds on open source projects
  • hiring systems engineer
  • ibm doesnt care about nodejs people
  • javascript trampoline party
  • nodejs training sessions
  • intern at nodejitsu
  • the west coast hack haus
  • ten node apps that need to exist
  • sessions and cookies in node
  • sending emails in node
  • kyuri and prenup our node knockout entries

about nodejitsu

nodejitsu is a node.js application hosting and martial arts training company.

we are evangelists and community leaders in the node.js project.

we build awesome open-source projects and keep your node.js apps running on our node.js hosting platform.

create node.js web-services in one line

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:

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!