Node by example

Node by example: 10. addon modules

10. addon modules

The complete source code can be downloaded here: http://github.com/Hendrik/node-by-example

The examples in this chapter are meant to showcase extending node with some of the available third party modules.
Websockets (server & client), MySQL access and GeoIP are covered in this chapter.

i) GeoIP:
The following example is based on the GeoIP module available at: http://github.com/strange/node-geoip

Please follow the installation instructions provided on above mentioned page.
Short version: you need to install & setup libGeoIP and build the module for the example to work.
See 10_addons/geoip.js:

/*  This example requires the GeoIP addon available at
 *  http://github.com/strange/node-geoip
 */

var sys = require("sys"),
  geoip = require("./lib/geoip");

var dbpath = "/usr/local/share/GeoIP/GeoLiteCity.dat";
var ip = "216.236.135.152";

sys.puts("Looking up IP: " + ip);
var con = new geoip.Connection(dbpath, function(con) {
  con.query(ip, function(result) {
    for (var attr in result) {
      sys.puts(attr + " : " + result[attr]);
    }
  });
});

 

First we need to include the geoip module:

var geoip = require("./lib/geoip");

 

Next is the location of the GeoLiteCity.dat file on your system:

var dbpath = "/usr/local/share/GeoIP/GeoLiteCity.dat";

 

In this example the GeoIP lookup will be made against the following IP:

var ip = "216.236.135.152";

 

Use geoip.Connection() to create a new GeoIP connection object:

var con = new geoip.Connection(dbpath, function(con) {
  ...
});

 

Then use con.query(ip, callback) to query the provided IP against the GeoIP database:

con.query(ip, function(result) {
  for (var attr in result) {
    sys.puts(attr + " : " + result[attr]);
  }
});

 

The output should be:

Looking up IP: 216.236.135.152
longitude : -73.97250366210938
latitude : 40.84830093383789
country_code : US
continent_code : NA
metro_code : 501
country : United States
city : Fort Lee
area_code : 201

 

One interesting use for this module is to parse your websites access log file in real time and have a google map updated in your browser with the location of your visitors using a websocket.

 

ii) MySQL connection:
In order to connect to MySQL we will use DBSlayer, a lightweight database abstraction layer.
You will need to install & configure DBSlayer and download the node.dbslayer.js module available at: http://github.com/shoeman22/node.dbslayer.js
Please follow the installation instructions at: http://github.com/shoeman22/node.dbslayer.js

Once configured you can run dbslayer via:
(assuming you setup the configuration at /etc/dbslayer.conf)

dbslayer -c /etc/dbslayer.conf -s lokidan -h 127.0.0.1

 

Please note: DBSlayer comes with limited security, so please make sure to add the "-h 127.0.0.1" option to allow requests from localhost only.

dbslayer.js itself can be executed via:

node dbslayer.js "SQL QUERY"

where "SQL QUERY" needs to be replaced with a SQL query based on your DBSlayer configuration.

 

For example:

# node dbslayer.js "SELECT id FROM notifications"
-------------------------
Row 0: 4
Row 1: 5
-------------------------
STAT Uptime: 3963181  Threads: 1  Questions: 319223  Slow queries: 0  Opens: 91107  Flush tables: 1  Open tables: 64  Queries per second avg: 0.081
-------------------------
CLIENT_INFO 5.0.90
-------------------------
HOST_INFO Localhost via UNIX socket
-------------------------
SERVER_VERSION 50090
-------------------------
CLIENT_VERSION 50090

 

 

iii) Websockets (Server & Client)
The Websocket server & client examples are each based on their own third party module.
For the Websocket server we use http://github.com/ncr/node.ws.js and for the Websocket client http://code.google.com/p/revhttp/source/browse/trunk/nodejs/node-ws-client.js
Both are already provided in the full source code and don't require any extra installation.

Let's start with the Websocket server. You will see that it is very similar to the http server setup:
See 10_addons/websocket_server.js:

var sys = require("sys"),
     ws = require("./lib/ws");

ws.createServer(function (websocket) {
  websocket.addListener("connect", function (resource) {
    sys.debug("connect: " + resource);
    websocket.write("test");
    setTimeout(websocket.end, 10 * 1000);
  });
  websocket.addListener("data", function (data) {
    sys.debug('DATA: ' + data);
    websocket.write("Thanks!");
  });
  websocket.addListener("close", function () {
    sys.debug("close");
  });
}).listen(8000);

 

First make sure to include the ws module:

var ws = require("./lib/ws");

 

Create the websocket server object, which provides the following event emitters:
"connect": when a connection is established to the websocket server
"data": when data is received by the websocket server
"close": when the connection gets closed

ws.createServer(function (websocket) {
...
}).listen(8000);

 

First the "connect" event, where we send out a "test" message to the connected client and start a timer to close the websocket after 10 seconds:

websocket.addListener("connect", function (resource) {
  sys.debug("connect: " + resource);
  websocket.write("test");
  setTimeout(websocket.end, 10 * 1000);
});

 

Output any received data to the console:

websocket.addListener("data", function (data) {
  sys.debug('DATA: ' + data);
  websocket.write("Thanks!");
});

 

Output a simple close message when the connection gets closed:

websocket.addListener("close", function () {
  sys.debug("close");
});

 

This is already it. You can connect to this websocket server using any browser that supports websockets or use the provided websocket client script to connect from node:

This websocket client example is based on the module available at: http://code.google.com/p/revhttp/source/browse/trunk/nodejs/node-ws-client.js

See 10_addons/websocket_client.js:

var sys = require("sys"),
     ws = require("./lib/node-ws-client");

var wsClient = ws.createClient('ws://127.0.0.1:8000/');

wsClient.addListener('connect', function() {
  sys.puts("Connected!");
  wsClient.write("Testing");
});

wsClient.addListener('data', function(chunk) {
  sys.puts("Received data: " + chunk);
});

wsClient.addListener('close', function() {
  sys.puts("Disconnected!");
});

setTimeout(function() {
  for(var i = 0; i<10; i++) {
    setTimeout(function() {
      wsClient.write("Hello WS world! " + Math.random().toString());
      sys.debug('data sent');
    }, i*200);
  }
}, 2000);

setTimeout(function() {
  wsClient.close();
}, 10000);

 

Same old, same old: first include the third party module:

var ws = require("./lib/node-ws-client");

 

Then create the Websocket client:

var wsClient = ws.createClient('ws://127.0.0.1:8000/');

 

The Websocket client provides the same emitters as the server object for "connect", "data" and "close" events.
In this example we send out a "Testing" message upon successful connection to the websocket server:

wsClient.addListener('connect', function() {
  sys.puts("Connected!");
  wsClient.write("Testing");
});

 

Any received data will be sent to the console:

wsClient.addListener('data', function(chunk) {
  sys.puts("Received data: " + chunk);
});

 

Add a simple "Disconnected!" output when the connection has been closed:

wsClient.addListener('close', function() {
  sys.puts("Disconnected!");
});

 

Next add a timer to send 10 random messages within a short interval to the Websocket server:

setTimeout(function() {
  for(var i = 0; i<10; i++) {
    setTimeout(function() {
      wsClient.write("Hello WS world! " + Math.random().toString());
      sys.debug('data sent');
    }, i*200);
  }
}, 2000);

 

And at last add another timer to automatically close the connection after 10 seconds:

setTimeout(function() {
  wsClient.close();
}, 10000);

 

If you have a browser that supports websockets, then you can use the websocket server & client modules for some nice streaming applications.
As mentioned above, one example would be to stream the locations of your website visitors to a google map in real time using a Websocket.