| 
									
										
										
										
											2014-02-05 15:28:23 +01:00
										 |  |  | #!/usr/bin/env node
 | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  | "use strict"; | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  | var dope = require("console-dope"), | 
					
						
							|  |  |  |     connect = require("connect"), | 
					
						
							| 
									
										
										
										
											2014-01-03 18:04:44 +00:00
										 |  |  |     http = require("http"), | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     Model = require("nature").Model, | 
					
						
							| 
									
										
										
										
											2014-02-26 15:10:46 +01:00
										 |  |  |     w = require("wodge"), | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     path = require("path"), | 
					
						
							|  |  |  |     loadConfig = require("config-master"), | 
					
						
							|  |  |  |     morgan = require("morgan"), | 
					
						
							|  |  |  |     serveStatic = require("serve-static"), | 
					
						
							| 
									
										
										
										
											2014-05-08 15:05:06 +02:00
										 |  |  |     directory = require("serve-index"), | 
					
						
							|  |  |  |     compress = require("compression"); | 
					
						
							| 
									
										
										
										
											2013-06-04 12:45:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-08 15:05:06 +02:00
										 |  |  | var usage = | 
					
						
							|  |  |  | "usage: \n\ | 
					
						
							|  |  |  | $ ws [--directory|-d <directory>] [--port|-p <port>] [--log-format|-f dev|default|short|tiny]\n\ | 
					
						
							|  |  |  | $ ws --compress|-c \n\ | 
					
						
							|  |  |  | $ ws --help|-h"; | 
					
						
							| 
									
										
										
										
											2014-02-05 15:28:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  | function halt(message){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |     dope.red.log("Error: %s",  message); | 
					
						
							|  |  |  |     dope.log(usage); | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  |     process.exit(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  | /* parse command-line args */ | 
					
						
							|  |  |  | var argv = new Model() | 
					
						
							| 
									
										
										
										
											2014-02-01 23:10:18 +01:00
										 |  |  |     .define({ name: "port", alias: "p", type: "number", defaultOption: true, value: 8000 }) | 
					
						
							| 
									
										
										
										
											2014-02-13 14:23:17 +01:00
										 |  |  |     .define({ name: "log-format", alias: "f", type: "string" }) | 
					
						
							| 
									
										
										
										
											2013-06-15 00:41:43 +01:00
										 |  |  |     .define({ name: "help", alias: "h", type: "boolean" }) | 
					
						
							| 
									
										
										
										
											2014-02-09 08:30:11 +01:00
										 |  |  |     .define({ name: "directory", alias: "d", type: "string", value: process.cwd() }) | 
					
						
							| 
									
										
										
										
											2014-05-08 15:05:06 +02:00
										 |  |  |     .define({ name: "config", type: "boolean" }) | 
					
						
							|  |  |  |     .define({ name: "compress", alias: "c", type: "boolean" }); | 
					
						
							| 
									
										
										
										
											2014-03-06 14:00:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  | /* Merge together options from "~/.local-web-server.json", "{cwd}/.local-web-server.json" and "{cwd}/package.json", in that order. */ | 
					
						
							|  |  |  | var storedConfig = loadConfig( | 
					
						
							|  |  |  |     path.join(w.getHomeDir(), ".local-web-server.json"), | 
					
						
							|  |  |  |     path.join(process.cwd(), ".local-web-server.json"), | 
					
						
							|  |  |  |     path.join(process.cwd(), "package.json:local-web-server") | 
					
						
							|  |  |  | ); | 
					
						
							| 
									
										
										
										
											2014-05-08 15:05:06 +02:00
										 |  |  | try { | 
					
						
							|  |  |  |     argv.set(storedConfig); | 
					
						
							|  |  |  | } catch (err){ | 
					
						
							|  |  |  |     dope.red.log("Failed to set stored config, please check your config files"); | 
					
						
							|  |  |  |     halt(err.message); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-26 15:23:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  | /* Finally, set the options from the command-line, overriding all defaults. */ | 
					
						
							| 
									
										
										
										
											2014-05-08 15:05:06 +02:00
										 |  |  | try { | 
					
						
							|  |  |  |     argv.set(process.argv); | 
					
						
							|  |  |  | } catch (err){ | 
					
						
							|  |  |  |     dope.red.log("Failed to set command line options"); | 
					
						
							|  |  |  |     halt(err.message); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  | /* Die here if invalid args received */ | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  | if (!argv.valid) halt(argv.validationMessages); | 
					
						
							| 
									
										
										
										
											2014-02-09 08:40:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-08 15:05:06 +02:00
										 |  |  | if (argv.config){ | 
					
						
							|  |  |  |     dope.log("Stored config: "); | 
					
						
							|  |  |  |     dope.log(storedConfig); | 
					
						
							|  |  |  |     process.exit(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } else if (argv.help){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |     dope.log(usage); | 
					
						
							| 
									
										
										
										
											2013-06-15 00:41:43 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | } else { | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  |     var total = { | 
					
						
							|  |  |  |         req: 0, | 
					
						
							|  |  |  |         bytes: 0, | 
					
						
							|  |  |  |         connections: 0 | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     process.on("SIGINT", function(){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |         dope.showCursor(); | 
					
						
							|  |  |  |         dope.log(); | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  |         process.exit(0); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* customised logger :date token, purely to satisfy Logstalgia. */ | 
					
						
							|  |  |  |     morgan.token("date", function(){ | 
					
						
							| 
									
										
										
										
											2013-06-15 00:41:43 +01:00
										 |  |  |         var a = new Date(); | 
					
						
							|  |  |  |         return (a.getDate() + "/" + a.getUTCMonth() + "/" + a.getFullYear() + ":" + a.toTimeString()) | 
					
						
							|  |  |  |                 .replace("GMT", "").replace(" (BST)", ""); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 21:13:13 +01:00
										 |  |  |     var app = connect(); | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* log using --log-format (if supplied), else output statics */ | 
					
						
							| 
									
										
										
										
											2014-02-13 14:23:17 +01:00
										 |  |  |     if(argv["log-format"]){ | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |         app.use(morgan(argv["log-format"])); | 
					
						
							| 
									
										
										
										
											2014-02-13 14:23:17 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2014-02-10 21:13:13 +01:00
										 |  |  |         app.use(function(req, res, next){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |             dope.column(1).write(++total.req); | 
					
						
							| 
									
										
										
										
											2014-02-10 21:13:13 +01:00
										 |  |  |             next(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* --compress enables compression */ | 
					
						
							|  |  |  |     if (argv.compress) app.use(compress()); | 
					
						
							| 
									
										
										
										
											2014-02-17 10:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* static file server including directory browsing support */ | 
					
						
							|  |  |  |     app.use(serveStatic(path.resolve(argv.directory))) | 
					
						
							|  |  |  |         .use(directory(path.resolve(argv.directory), { icons: true })); | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* launch server */ | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  |     var server = http.createServer(app) | 
					
						
							| 
									
										
										
										
											2014-03-06 14:00:50 +01:00
										 |  |  |         .on("error", function(err){ | 
					
						
							|  |  |  |             if (err.code === "EADDRINUSE"){ | 
					
						
							|  |  |  |                 halt("port " + argv.port + " is already is use"); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 halt(err.message); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  |         .listen(argv.port); | 
					
						
							| 
									
										
										
										
											2013-06-15 00:41:43 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* write status to stderr so stdout can be piped to disk ($ ws > log.txt) */ | 
					
						
							| 
									
										
										
										
											2014-03-06 14:00:50 +01:00
										 |  |  |     if (path.resolve(argv.directory) === process.cwd()){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |         dope.error("serving at %underline{%s}", "http://localhost:" + argv.port); | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |         dope.error("serving %underline{%s} at %underline{%s}", argv.directory, "http://localhost:" + argv.port); | 
					
						
							| 
									
										
										
										
											2014-02-12 10:52:07 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 11:28:15 +01:00
										 |  |  |     /* in stats mode, monitor connections and bytes transferred */ | 
					
						
							| 
									
										
										
										
											2014-02-13 14:23:17 +01:00
										 |  |  |     if (!argv["log-format"]){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |         dope.hideCursor(); | 
					
						
							|  |  |  |         dope.log("%underline{Requests}   %underline{Data}        %underline{Connections}"); | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  |         server.on("connection", function(socket){ | 
					
						
							|  |  |  |             var oldWrite = socket.write; | 
					
						
							|  |  |  |             socket.write = function(data) { | 
					
						
							|  |  |  |                 if (!Buffer.isBuffer(data)) { | 
					
						
							|  |  |  |                     data = new Buffer(data); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 oldWrite.call(this, data); | 
					
						
							|  |  |  |                 total.bytes += data.length; | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |                 dope.column(12).write(w.padRight(w.bytesToSize(total.bytes, 2), 12)); | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  |             }; | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |             dope.column(24).write(++total.connections); | 
					
						
							| 
									
										
										
										
											2014-02-13 14:26:42 +01:00
										 |  |  |             socket.on("close", function(){ | 
					
						
							| 
									
										
										
										
											2014-03-12 14:34:52 +01:00
										 |  |  |                 dope.column(24).write(w.padRight(--total.connections)); | 
					
						
							| 
									
										
										
										
											2014-02-13 14:26:42 +01:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2014-02-12 13:22:30 +01:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-15 00:41:43 +01:00
										 |  |  | } |