Search This Blog

Showing posts with label expressjs. Show all posts
Showing posts with label expressjs. 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!