diff --git a/LICENSE b/LICENSE index 1e989b448..ee0335634 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011 Charlie Robbins, Marak Squires, and the Contributors. +Copyright (c) 2011 Charlie Robbins, Marak Squires, and the Contributors & Me. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 20eb7720e..3ffb35d78 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# http-server: a command-line http server +# watch-http-server: a command-line http server -`http-server` is a simple, zero-configuration command-line http server. It is powerful enough for production usage, but it's simple and hackable enough to be used for testing, local development, and learning. +`watch-http-server` is a simple, zero-configuration command-line http server. -![](https://github.com/nodeapps/http-server/raw/master/screenshots/public.png) +It simply injects a very small javascript include right before the body tag of your HTML documents, whereby +a websocket connection is made on the host, triggering a reload of the page. Currently this happens when +any item in the folder changes but it may soon be made to be specific relevant to the loaded document. # Installing globally: @@ -12,38 +14,25 @@ Installation via `npm`. If you don't have `npm` yet: Once you have `npm`: - npm install http-server -g + npm install -g watch-http-server -This will install `http-server` globally so that it may be run from the command line. +This will install `watch-http-server` globally so that it may be run from the command line. ## Usage: - http-server [path] [options] + watch-http-server [path] [options] + (or alternatively, whs or watchhttpserver) `[path]` defaults to `./public` if the folder exists, and `./` otherwise. -# Installing as a node app - - mkdir myapp - cd myapp/ - jitsu install http-server - -*If you do not have `jitsu` installed you can install it via `npm install jitsu -g`* - ## Usage -### Starting http-server locally +### Starting watch-http-server locally - node bin/http-server + node bin/watch-http-server *Now you can visit http://localhost:8080 to view your server* -### Deploy http-server to nodejitsu - - jitsu deploy - -*You will now be prompted for a `subdomain` to deploy your application on* - ## Available Options: `-p` Port to use (defaults to 8080) @@ -69,6 +58,3 @@ This will install `http-server` globally so that it may be run from the command `-K` or `--key` Path to ssl key file (default: key.pem). `-h` or `--help` Print this list and exit. - -`-c` Set cache time (in seconds) for cache-control max-age header, e.g. -c10 for 10 seconds -(defaults to '3600'). To disable caching, use -c-1. diff --git a/lib/http-server.js b/lib/http-server.js index 051a239bf..533083e60 100644 --- a/lib/http-server.js +++ b/lib/http-server.js @@ -1,7 +1,10 @@ var fs = require('fs'), util = require('util'), union = require('union'), - ecstatic = require('ecstatic'); + sexstatic = require('sexstatic'), + ws = require('ws'), + portfinder = require('portfinder'), + chokidar = require('chokidar'); var HTTPServer = exports.HTTPServer = function (options) { options = options || {}; @@ -19,6 +22,96 @@ var HTTPServer = exports.HTTPServer = function (options) { } } + var hotReloadScript = ' \ + var xhr = new XMLHttpRequest(); \n \ + if (typeof(window.reloadOnChange) == "undefined") \n \ + window.reloadOnChange = true; \n \ + \n \ + xhr.onreadystatechange = function() { \n \ + if (xhr.readyState == 4) \n \ + { \n \ + var resp = JSON.parse(xhr.responseText); \n \ + var changeSocket = new WebSocket("ws://"+location.hostname+":"+resp.port+"/"); \n \ + changeSocket.onopen = function() { console.log("-- change socket opened, observing changes --") } \n \ + changeSocket.onmessage = function(ev) { \n \ + if (ev.data.indexOf("change") != -1) { \n \ + setTimeout(function() { \n \ + if (window.reloadOnChange) { \n \ + console.log("change detected: reloading --"); \n \ + window.location.reload(); \n \ + }}, 1000); \n \ + } \n \ + if (ev.data.indexOf("folder") != -1 && document.querySelector("title").innerText.indexOf("Index of") != -1) { \n \ + console.log("folder change, reloading"); \n \ + window.location.reload(); \n \ + } \n \ + } \n \ + }} \n \ + xhr.open("GET", "ws.json", true); \n\ + xhr.send(null); \ + '; + + var mutableExtras = { + 'http-hot-reload.js': { + 'content-type': 'text/javascript', + 'content': hotReloadScript + }, + 'ws.json': { + 'content-type': 'text/json', + 'content': JSON.stringify({ + port: this.wsPort, + path: this.root, + additional: "file untouched. the ws server probably isn't running." + }) + } + } + + portfinder.basePort = 8086; + portfinder.getPort(function (err, port) { + if (err) { console.log("Error, no open ports available."); console.dir(err); return; } + + this.wsPort = port; + console.log('Websocket Server Listening on Port: '+port); + + this.wss = new ws.Server({port: port}); + this.wss.broadcast = function broadcast(data) { + for(var i in this.clients) { + try { this.clients[i].send(data); } catch (ex) { console.log('error sending to client.'); console.dir(ex); } + } + }; + + // + + mutableExtras['ws.json'].content = JSON.stringify({ + port: this.wsPort, + path: this.root + }); + + var watcher_ready = false; + + var watcher = chokidar.watch(this.root, {ignored: /[\/\\]\./, persistent: true}); + + watcher.on('ready', function() { console.log('Scanned working directory. ready for changes..'); watcher_ready = true; }); + watcher.on('unlinkDir', function(path) { + if (!watcher_ready) return; + this.wss.broadcast('folder|'+path); + }.bind(this)); + watcher.on('addDir', function(path) { + if (!watcher_ready) return; + this.wss.broadcast('folder|'+path); + }.bind(this)); + watcher.on('add', function(path) { + if (!watcher_ready) return; + this.wss.broadcast('folder|'+path); + }.bind(this)); + watcher.on('change', function(filename) { + if (!watcher_ready) return; + console.log('change detected! telling clients to reload. ['+filename+']'); + this.wss.broadcast('changed|'+filename); + }.bind(this)); + }.bind(this)); + + if (options.headers) { this.headers = options.headers; } @@ -33,6 +126,15 @@ var HTTPServer = exports.HTTPServer = function (options) { : options.ext; } + function addReloadScript(src) + { + var index = src.indexOf(" - - 404 - - -

404

- -

Were you just making up filenames or what?

- - diff --git a/public/img/turtle.png b/public/img/turtle.png deleted file mode 100644 index 721a796bb..000000000 Binary files a/public/img/turtle.png and /dev/null differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 12cafb2ec..000000000 --- a/public/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - node.js http server - - - -

Serving up static files like they were turtles strapped to rockets.

- - - - - diff --git a/screenshots/public.png b/screenshots/public.png deleted file mode 100644 index aa007bdc7..000000000 Binary files a/screenshots/public.png and /dev/null differ diff --git a/test.txt b/test.txt new file mode 100644 index 000000000..f2d7933bf --- /dev/null +++ b/test.txt @@ -0,0 +1 @@ +asds \ No newline at end of file