Saturday, 15 April 2017

Looking for a cleaner way to run NodeJS as a service with absolute paths

I have a NodeJS project that starts with server.js under /opt/battleship. If I cd to that dir and type node server, everything works correctly, but if I sit in /root and use an absolute path to start it up, such as node /opt/battleship/server, then everything I serve from its ./lib and ./public subdirs gets a 404 response. This is a problem in production because my /etc/init/battleship.conf script specifies starting the process on boot with

exec /usr/local/bin/node /opt/battleship/server.js >> /var/log/battleship.log 2>&1

It runs, but then I get the 404 errors. If I put the line

cd /opt/battleship

just above that in the battleship.conf file, I don't get 404 errors, I get all my files correctly, but it seems as if using cd in a .conf file is messy and prone to errors. Correct me if I'm wrong, this is my first handwritten .conf file. Is there a better way to have my server.js server up files correctly from its ./lib and ./public subdirectories? Below is my server.js file for reference:

var PORT      = 3000;

var requirejs = require('requirejs');
var http      = requirejs('http');
var fs        = requirejs('fs');
var path      = requirejs('path');
var mime      = requirejs('mime');
var cache     = {};

requirejs.config({
    baseUrl: __dirname,
    nodeRequire: require,
        packages: [
            {name: 'ship', location: 'public/js/lib/ship'},
            {name: 'GameState', location: 'public/js/lib', main: 'GameState'}
    ]   
});

requirejs(['./lib/battleship_server'], function(battleship_server) {
    function send404(response) {
        response.writeHead(404, {'Content-Type': 'text/plain'});
        response.write('Error 404: response not found.');
        response.end();
    }

    function sendFile(response, filePath, fileContents) {
        response.writeHead(
            200,
            {'Content-Type': mime.lookup(path.basename(filePath))}
        );
        response.end(fileContents);
    }

    function serveStatic(response, cache, absPath) {
        if (cache[absPath]) {
            sendFile(response, absPath, cache[absPath]);
        } else {
            fs.exists(absPath, function(exists) {
                if (exists) {
                    fs.readFile(absPath, function(err, data) {
                        if (err) {
                            send404(response);
                        } else {
                            cache[absPath] = data;
                            sendFile(response, absPath, data);
                        }
                    });
                } else {
                    send404(response);
                }
            });
        }
    }

    var server = http.createServer(function(request, response) {
        var filePath = false;

        if (request.url === '/') {
            filePath = 'public/index.html';
        } else {
            filePath = 'public' + request.url;
        }
        var absPath = './' + filePath;
        serveStatic(response, cache, absPath);
    });

    server.listen(PORT, function() {
        console.log('Server listening on port ' + PORT + '.');
    });

    battleship_server(server);
});



via Zack Stauber

No comments:

Post a Comment