Search This Blog

Showing posts with label nodejs. Show all posts
Showing posts with label nodejs. Show all posts

Saturday, May 31, 2014

How To: Run a clustered NodeJs app under secured connection

Let me take a few moments to explain the basics and then we'll start:

1. A clustered nodejs app allows you to create several processes (equals to the number of cores you have on your server) that run the same application on the same port.
2. A secured nodejs app allows you to receive and return data on a secure line.

This tutorial should be very short and very practical. Let's start..

1. Requirements

var express = require("express");
var cluster = require('cluster');
var fs = require('fs');
var https = require('https');

2. Initialisations

var sslPort = 443;
var sslOptions = {pfx: fs.readFileSync('personal.pfx'),passphrase: '123456'};


The sslPort variable is kind of fixed, but you know.. I'm trying to give you as much freedom as i can
The ssOptions varible is a JSON object that decalres a .pfx or .pem,
in case of a .pfx file usage like in our example, we need to declare a 'passphrase' property with the private password of the .pfx file.

3. App definition

var app = express();
var numCPUs = require('os').cpus().length;
console.log("Num of cpus up: " + numCPUs);

Now we'll get the number of cpus working for our app.

4. Cluster definition

if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
console.log(i + " - fork.");
}

  cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {

// your routes goes here.
app.get(.........


If the instance is a master, it will let other instances to fork it, if not - well.. start the server :)

Note that we didn't close the 'else' section.

5. The tricky part - configure the cluster to listen to a secure port from all the instances

After we finished our routings, we need to let the server to start listening.
For this matter, we will override the server 'listen' method and create our own:

app.listen = function(){
var server = https.createServer(sslOptions, this);
return server.listen.apply(server, arguments);
};


The sslOptions varible is the same one we defined in the "Initialisations" section (2).

6. And last - Listen!

app.listen(sslPort, function(){
logger.module('cluster').debug("Express server listening on port: " + sslPort);
});
} // else cluster


Note that we closed the 'else' section from the Cluster definition part (2).

Tuesday, March 25, 2014

HOW TO: Write a Node.js service that accepts POST requests like a boss

I found it very difficult to create a service that can handle a post request sent from other applications in Node.js.
So, I took my laptop and started  searching..

I found all sort of tutorials that led me to things like:
// ?name=tobi
req.param('name')
// => "tobi"

// POST name=tobi
req.param('name')
// => "tobi"

// /user/tobi for /user/:name
req.param('name')
// => "tobi"
BUT IT DIDN'T WORK!

All i got was null, undefined and {}
And I wasn't alone!
stackoverflow is full with questions about this subject and each and every one of them have a different answer!

The obvious decision was to stay with expressjs or with connect and try to make them work.

Well, I found out that W3 provides two regulations for POST request encoding:
1. multipart/form-data
2. application/x-www-form-urlencoded
While application/x-www-form-urlencoded is the more common type of encoding and multipart/form-data is used mostly for uploading files.

And the tools i was using ware configured to the second one "application/x-www-form-urlencoded".

So how did I make it work?!
I've bundled myself this Node.js snippet:
(requires node-querystring)

var encoder = require('querystring');
app.post('/postman', function(req, res) {
var Body='';
req.on('data', function(chunk) {
Body += chunk.toString();
});

req.on('end', function() {
res.writeHead(200, "OK", {'Content-Type': 'text/html'});
var decodedBody = encoder.parse(Body);
console.log(decodedBody.name);
console.log(decodedBody);
res.end();
});
});



Testing your service!
I like to use these two tools:
1. curl from Terminal
curl --data "name=value1" http://localhost:3000/Postman/
curl -XPOST http://localhost:3000/Postman -d 'name=val1'
2. Postman from Chrome Web browser


Accessing from your app!

Sunday, January 19, 2014

Run Node.js as a service on ubuntu

In this tutorial we will host a new node.js service on ubuntu linux using upstart.

Assuming you have a working node.js "Hello World!" kind of service.


var http = require("http");


var url  = require('url');




http.createServer(function(request, response) {


  response.write("Hello World!");


  response.end();


}).listen(8888);


This particular service listens to the port 8888.

http://localhost:8888

So now all we have to do left is make it run as a service [optional: and run on startup]

Install upstart



sudo apt-get install upstart

Cofigure your script



vi /etc/init/nodejs_server.conf
#!upstart
description "node.js server"
author "Rasta"

start on starting networking
stop on shutdown

script
export HOME="/home/USER_NAME"

echo $$ > /var/run/SERVICE_NAME.pid
exec sudo -u
USER_NAME /usr/bin/node ~/nodejs/server.js >> /var/log/nodejs_server.log 2>&1
end script

pre-start script
# Date format same as (new Date()).toISOString() for consistency
echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/nodejsserver.log
end script

Now let's go over this..
start on starting networking
stop on shutdown

upstart allows us to determine when the script will be activated.
We want the nodejs service to be up and running whenever the network is ready to be used,
and be shutdown along with the machine.

The script


script
export HOME="/home/USER_NAME"

echo $$ > /var/run/SERVICE_NAME.pid
exec sudo -u
USER_NAME PATH FILE.js >> /var/log/nodejs_server.log 2>&1
end script

Our variables:

  1. USER_NAME - the name of the user that will run the service
  2. SERVICE_NAME - will be displayed in your "ps" command
  3. PATH - is where the nodejs executables are , usually it's "/usr/bin/node" or "/usr/local/bin/node"
  4. FILE.js - is your hello world service. you need to use "~/path" to concatenate the file path to your HOME variable.
Pre-start script


pre-start script
# Date format same as (new Date()).toISOString() for consistency
echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/nodejsserver.log
end script

Will just get you informed that the service is starting..

Manually start/stop

[sudo] /sbin/start nodejs_server
[sudo] /sbin/stop nodejs_server

Read the log

Read the log file to check for errors and Node.js's console.log command.
cat /var/log/nodejs_server.log