Building a modular system based on Nodejs

Primary requirements


• ease of connecting modules
• standard URL structure
• multilingualism
• automatic change acceptance
• use of multiprocessor system capabilities
The system is based on Express . The wait.for module is used to facilitate writing code .

File structure


  • root
    • routes
      • mod_api
        • test.js
      • api.js
    • views
    • public
    • app.js
    • Server.js


Linux server demonization


In our project, the forever module was used .
-w - allows changing modules without directly rebooting the server. Forever monitors changes and overloads the server as needed.
-l leads to the void, as it was decided that two logs is too much.
forever start -a -w -l /dev/null -o out.log -e err.log Server.js

Using the capabilities of a multiprocessor system


Launching multiple processes through the “cluster” module to distribute the load between the cores.
//файл Server.js
var cluster = require('cluster');
var workerCount = require('os').cpus().length;
cluster.setupMaster({ exec: "app.js" });
// Fork workers.
for (var i = 0; i < workerCount ; i++)cluster.fork()

Module connections


The ease of connecting modules is achieved by two switches.
Automatically connect all routes

// part of app.js
// путь к routes относительно запускаемого файла
var routesPath = path.join(__dirname, 'routes');
//лист всех файлов в директории
var routeList = fs.readdirSync(routesPath);
for(var i in routeList){
    var filePath = path.join(routesPath,routeList[i]);
    if(fs.statSync(filePath).isFile() && path.extname(routeList[i])=='.js')
        require(filePath)(app); // инициация путей
}

Module connection and function call

Routes are defined separately. in each file, how unification and ease of connecting routes for the end developer are also achieved.
//файл api.js
module.exports = function (app) {
    app.get('/api/:mod/:lang/:action', function(req, res){action(req,res,global.conf.METHODS.GET);});
    app.post('/api/:mod/:lang/:action', function(req, res){action(req,res,global.conf.METHODS.POST);});
    app.delete('/api/:mod/:lang/:action', function(req, res){action(req,res,global.conf.METHODS.DELETE);});
    app.put('/api/:mod/:lang/:action', function(req, res){action(req,res,global.conf.METHODS.PUT);});
};
function action(req, res, method) {
    //проверка языка
    var lang = req.params.lang.toUpperCase();
    if (global.conf.AVAILABLE_LANGUAGES.indexOf(lang) > -1) {
      // чистка имени модуля 
	var mod = req.params.mod.replace(/[^a-zA-z0-9]+/g,'');
      // чистка имени функции
	var action = req.params.action.replace(/[^a-zA-z0-9]+/g,'');
      // проверка существования модуля  
	fs.exists(path.resolve(__dirname, './mod_api/'+mod+".js"),function(ok){
            if(ok){
		   // вызов модуля
                var startMode = require('./mod_api/'+mod);
                try{
		    // вызов функции с префиксом pub_
                    wait.launchFiber(startMode['pub_'+action], req, res, lang, method);
                }catch(err){
                    res.status(405).pj(405,err.message,"Method Not Allowed");
                }
            }else{
                res.status(503).pj(503,null,'Service Unavailable ');
            }
        });
    }
    else{
        res.status(400).pj(400,null,'Not supported language');
    }
}

Implementation of the final function


All functions with the prefix pub_ are public, everything else is private.
// file routes/mod_api/test.js
exports.pub_Start = function(req, res, lang, method){   
   res.pj(0,(method===global.conf.METHODS.POST)?"POST":"GET","SUCCESS ");
}

Output unification


//part app.js
http.ServerResponse.prototype.pj = function(status,data,message){
    try {
        this.json({STATUS:status,CONTENT:data,MESSAGE:message});
    }catch(e) {
        console.error(e);
        this.json({STATUS:999,CONTENT:null,MESSAGE:'parse response error'});}
};


Well, at the end, the function call: api.codevit.net/api/test/en/Start
(I really hope that the server does not crash, this is my test server)

If someone is interested, I can put the skeleton on github.
Please write about syntax errors in private.

Also popular now: