Cleaner Node Server REST API Implementation

My colleague Cyrille Fauvel provided some suggestions for me to apply various best practices to my Node.js WebGL viewer server implementation and its interactive testing framework:

Criteria to choose the rendering engine

Question: You listed a couple of different rendering engines, then picked Swig, not EJS. Can you explain why? I use EJS myself.

Answer: I picked the ones that looked smallest and easiest to get started with. I ended up implementing support for both Swig and Handlebars, with hardly any differences.

Presumably I could add support for EJS equally easily. I just need to find time to take a look at it.

Eliminate explicit request method checking

Suggestion: I like your incremental API implementation with separate handlers for the routes api/v1 and api/v2.

The implementation of routes/api.js is not so nice, though, using if clauses testing the request method to distinguish between GET and POST.

How about implementing a separate API router class doing it like this instead:

var express =require ('express') ;
var router1 =express.Router () ;
router1.use (bodyParser.json ()) ;

router1.get ('/', function(req, res) {
    res.send('API v1 GET: Hello World!');
});
router1.post ('/', function(req, res) {
    res.send('API v1 POST: '
      + JSON.stringify(req.body));
});
module.exports.v1 =router1 ;

var router2 =express.Router () ;
router2.use (bodyParser.json ()) ;
router2.get ('/', function(req, res) {
    res.send('API v2 GET: Here belongs a succinct '
      + 'explanation how to use The Building Coder '
      + 'WebGL Viewer REST API v2...');
});
Router2.post ('/', function(req, res) {
    console.log('API v2 POST: ' + JSON.stringify(req.body));
    res.render('viewer', req.body);
});
module.exports.v2 =router2 ;

I much prefer this to lots of if clauses which make things hard to read and maintain.

Complete Node.js Server Implementation

Following Cyrille's advice, I reimplemented the API request handler.

The node.js server still consists of the same three main pieces:

I updated the first two of those according to Cyrille's suggestions.

First, I replaced the if clauses testing the request method in the API implementation and simply returned four separate functions instead of two:

exports.v1get = function(req, res) {
  res.send('API v1 GET: Hello World!');
}

exports.v1post = function(req, res) {
  res.send('API v1 POST: '
    + JSON.stringify(req.body));
}

exports.v2get = function(req, res) {
  res.send('API v2 GET: Here belongs a succinct '
    + 'explanation how to use The Building Coder '
    + 'WebGL Viewer REST API v2...');
}

exports.v2post = function(req, res) {
  console.log('API v2 POST: ' + JSON.stringify(req.body));
  res.render('viewer', req.body);
}

Now, in the mainline implementation in server.js, I can provide those four directly to the app get and post functions:

var express = require('express');
var app = express();

app.set('port', (process.env.PORT || 5000));

app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res) {}); // leads to public/index.html

var bodyParser = require('body-parser');
app.use( bodyParser.json({ limit: '1mb' }) );
app.use( bodyParser.urlencoded({ extended: true, limit: '1mb' }) );

app.set('views', __dirname + '/views');

var use_swig_render = false;

if( use_swig_render ) {
  var swig = require('swig');
  app.engine('swig', swig.renderFile);
  app.set('view engine', 'swig');
  swig.setDefaults({ cache: false });
  app.set('view cache', false);
}
else {
  var handlebars = require('express-handlebars');
  app.engine('handlebars', handlebars());
  app.set('view engine', 'handlebars');
}

var api = require('./routes/api');

app.get('/api/v1', api.v1get);
app.post('/api/v1', api.v1post);

app.get('/api/v2', api.v2get);
app.post('/api/v2', api.v2post);

app.listen(app.get('port'), function() {
  console.log('Node WebGL app with '
    + (use_swig_render ? 'swig' : 'handlebars')
    + ' is running at localhost:'
    + app.get('port'));
});

The entire functionality seen by the outside world remains completely unchanged, so the previous API v1 and the enhanced v2 continue to run unaffected and can be exercised from the same unmodified interactive testing framework.

Download

The complete node server implementation is available from the NodeWebGL GitHub repo, and the version discussed here is 0.2.7.