From 4761ad6b34f352da506b1c0d08489138e623e038 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Mon, 2 Feb 2015 09:52:31 +0000 Subject: [PATCH] many: Initial 0.1.0 version. --- .jshintrc | 30 ++++++++++++++++++ LICENSE | 8 +++++ bin.js | 39 +++++++++++++++++++++++ lib/arguments.js | 40 ++++++++++++++++++++++++ lib/config.js | 58 +++++++++++++++++++++++++++++++++++ lib/logger.js | 28 +++++++++++++++++ lib/spserver.js | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 29 ++++++++++++++++++ 8 files changed, 312 insertions(+) create mode 100644 .jshintrc create mode 100644 LICENSE create mode 100644 bin.js create mode 100644 lib/arguments.js create mode 100644 lib/config.js create mode 100644 lib/logger.js create mode 100644 lib/spserver.js create mode 100644 package.json diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..6ca60f5 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,30 @@ +{ + "eqeqeq": true, + "forin": true, + "immed": true, + "newcap": true, + "noarg": true, + "noempty": true, + "nonew": true, + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "indent": 2, + "quotmark": "single", + "maxdepth": 4, + "boss": true, + "eqnull": true, + "globalstrict": true, + "smarttabs": true, + "browser": true, + "node": true, + "predef": [ + "describe", + "it", + "before", + "beforeEach", + "after", + "afterEach" + ] +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ae782ef --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +Copyright (c) 2015 Jonatan Nilsson + + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://www.wtfpl.net/ for more details. diff --git a/bin.js b/bin.js new file mode 100644 index 0000000..58a7268 --- /dev/null +++ b/bin.js @@ -0,0 +1,39 @@ +#!/usr/bin/env node +'use strict'; + +var config = require('./lib/config'); +var server = require('./lib/spserver'); + +var env = config.get('NODE_ENV'); + +//Check if we any +var displayHelp = config.get('help'); +if (!config.get('file') && !config.get(env + ':file') && + !config.get('serve') && !config.get(env + ':serve')) { + displayHelp = true; +} + +if (displayHelp) { + console.log('Run static server for static files, simple servers or pure MVVM projects.'); + console.log('Specifying either file or folder serving is required.'); + console.log(''); + console.log('Usage:'); + console.log(' spserver [options]'); + console.log(''); + console.log(config.stores.argv.help()); + console.log('Examples:'); + console.log(' spserver -p 2000 -f base.html -s ./dist'); + console.log(''); + console.log(' Will run the server on port 2000 serving static files from the ./dist folder'); + console.log(' with any unknown file being served the contents of base.html.'); + console.log(''); + console.log(' spserver -f base.html -t --custom test'); + console.log(''); + console.log(' Will run the server with the base.html as a template as well as'); + console.log(' passing the contents of "test" argument into the template.'); + + process.exit(0); +} + +//Run our server \o/ +server(); diff --git a/lib/arguments.js b/lib/arguments.js new file mode 100644 index 0000000..ba2e31e --- /dev/null +++ b/lib/arguments.js @@ -0,0 +1,40 @@ +'use strict'; + +module.exports = { + config: { + alias: 'c', + describe: 'Location of the config file for the server [default: config.json]' + }, + port: { + alias: 'p', + describe: 'The port server should bind to [default: 3001 or 80 in production mode]' + }, + file: { + alias: 'f', + describe: 'Single static file the server should serve on all unknown requests' + }, + bunyan: { + alias: 'b', + describe: 'Use bunyan instead of console to log to [default: true in production mode]' + }, + template: { + alias: 't', + describe: 'Parse the static file as lodash template with all options/settings being passed to it' + }, + name: { + alias: 'n', + describe: 'The name for this server for logging [default: spserver]' + }, + serve: { + alias: 's', + describe: 'Folder path to serve static files from [default: public]' + }, + prod: { + alias: 'P', + describe: 'Force run the server in production mode' + }, + debug: { + alias: 'd', + describe: 'Force run the server in development mode' + } +}; diff --git a/lib/config.js b/lib/config.js new file mode 100644 index 0000000..9ea9cf0 --- /dev/null +++ b/lib/config.js @@ -0,0 +1,58 @@ +'use strict'; + +var nconf = require('nconf'); + +//Load arguments as highest priority +nconf.argv(require('./arguments')); + +//Overrides +var overrides = {}; + +if (nconf.get('prod')) { + overrides.NODE_ENV = 'production'; +} +else if (nconf.get('debug')) { + overrides.NODE_ENV = 'development'; +} + +//Load overrides as second priority +nconf.overrides(overrides); + + +//Load enviroment variables as third priority +nconf.env(); + + +//Load the config if it exists. +nconf.file(nconf.get('config') || './config.json'); + + +//Default variables +nconf.defaults({ + name: nconf.get('name') || 'spserver', + NODE_ENV: 'development', + production: { + port: 80, + bunyan: { + name: nconf.get('name') || 'spserver', + streams: [{ + stream: 'process.stdout', + level: 'info' + } + ] + }, + }, + development: { + port: 3001, + bunyan: { + name: nconf.get('name') || 'spserver', + streams: [{ + stream: 'process.stdout', + level: 'debug' + } + ] + }, + } +}); + +module.exports = nconf; diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 0000000..8f53dc1 --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,28 @@ +'use strict'; + +var _ = require('lodash'); +var bunyan = require('bunyan'); + +//Get the config +var config = require('./config'); + +//Create our variables +var env = config.get('NODE_ENV'); +var output; + +if (config.get('bunyan') || config.get(env + ':use_bunyan')) { + var settings = _.cloneDeep(config.get(env + ':bunyan')); + + for (var i = 0; i < settings.streams.length; i++) { + if (settings.streams[i].stream === 'process.stdout') { + settings.streams[i].stream = process.stdout; + } + } + + output = bunyan.createLogger(settings); +} else { + output = console; + console.debug = console.log.bind(console); +} + +module.exports = output; diff --git a/lib/spserver.js b/lib/spserver.js new file mode 100644 index 0000000..aea9ffb --- /dev/null +++ b/lib/spserver.js @@ -0,0 +1,80 @@ +'use strict'; + +var fs = require('fs'); +var http = require('http'); +var _ = require('lodash'); +var nStatic = require('node-static'); + + +var config = require('./config'); +var logger = require('./logger'); + +var env = config.get('NODE_ENV'); +var fileServer = new nStatic.Server(config.get('serve') || config.get(env + ':serve')); + +module.exports = function(settings) { + if (!settings) { + settings = config.get(); + } + if (!settings[env]) { + settings[env] = {}; + } + + var base = generateBase(settings.file || settings[env].file, settings); + + var server = http.createServer(function (req, res) { + logger.debug('[REQ] GET:', req.url); + var startTime = new Date().getTime(); + + var done = function() { + var requestTime = new Date().getTime() - startTime; + logger.debug('[RES] GET:', req.url, '(' + res.statusCode + ') took', requestTime, 'ms'); + }; + + res.addListener('finish', done); + res.addListener('close', done); + + //return base(req, res); + req.addListener('end', function () { + fileServer.serve(req, res, function(e) { + if (!e) return; + if (e && e.status === 404 && base) { + return base(req, res); + } + logger.error(e); + res.writeHead(404); + res.end(); + }); + }).resume(); + }); + + server.listen(settings.port || settings[env].port); + + logger.info('Static server', + settings.name, + 'is listening on port', + settings.port || settings[env].port, + 'with public folder', + settings.serve || settings[env].serve); +}; + +function generateBase(file, settings) { + if (!file) { + return null; + } + + if (_.endsWith(file, 'js')) { + return require(file); + } + + var contents = fs.readFileSync(file); + + if (settings.template || settings[env].template) { + contents = _.template(contents)(settings); + } + + return function(req, res) { + res.writeHead(200, {'Content-Type': 'text/html'}); + res.end(contents); + }; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8bb9d4b --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "node-spserver", + "version": "0.1.0", + "description": "Node static page server for running quick MVVM file server", + "main": "lib/spserver.js", + "scripts": { + "test": "mocha --reporter spec ./test/*.test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/TheThing/node-spserver.git" + }, + "keywords": [ + "MVVM", + "server" + ], + "author": "Jonatan Nilsson", + "license": "WTFPL", + "bugs": { + "url": "https://github.com/TheThing/node-spserver/issues" + }, + "homepage": "https://github.com/TheThing/node-spserver", + "dependencies": { + "bunyan": "^1.3.3", + "lodash": "^3.0.1", + "node-static": "^0.7.6" + }, + "bin": "./bin.js" +}