Skip to content

Commit 2f962f4

Browse files
committed
added watcher stuff
1 parent bb362cf commit 2f962f4

File tree

8 files changed

+137
-61
lines changed

8 files changed

+137
-61
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2011 Charlie Robbins, Marak Squires, and the Contributors.
1+
Copyright (c) 2011 Charlie Robbins, Marak Squires, and the Contributors & Me.
22

33
Permission is hereby granted, free of charge, to any person obtaining
44
a copy of this software and associated documentation files (the

README.md

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
# http-server: a command-line http server
1+
# watch-http-server: a command-line http server
22

3-
`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.
3+
`watch-http-server` is a simple, zero-configuration command-line http server.
44

5-
![](https://github.com/nodeapps/http-server/raw/master/screenshots/public.png)
5+
It simply injects a very small javascript include right before the </body> tag of your HTML documents, whereby
6+
a websocket connection is made on the host, triggering a reload of the page. Currently this happens when
7+
any item in the folder changes but it may soon be made to be specific relevant to the loaded document.
8+
9+
![](https://github.com/nodeapps/watch-http-server/raw/master/screenshots/public.png)
610

711
# Installing globally:
812

@@ -12,38 +16,24 @@ Installation via `npm`. If you don't have `npm` yet:
1216

1317
Once you have `npm`:
1418

15-
npm install http-server -g
19+
npm install watch-http-server -g
1620

17-
This will install `http-server` globally so that it may be run from the command line.
21+
This will install `watch-http-server` globally so that it may be run from the command line.
1822

1923
## Usage:
2024

21-
http-server [path] [options]
25+
watch-http-server [path] [options]
2226

2327
`[path]` defaults to `./public` if the folder exists, and `./` otherwise.
2428

25-
# Installing as a node app
26-
27-
mkdir myapp
28-
cd myapp/
29-
jitsu install http-server
30-
31-
*If you do not have `jitsu` installed you can install it via `npm install jitsu -g`*
32-
3329
## Usage
3430

35-
### Starting http-server locally
31+
### Starting watch-http-server locally
3632

37-
node bin/http-server
33+
node bin/watch-http-server
3834

3935
*Now you can visit http://localhost:8080 to view your server*
4036

41-
### Deploy http-server to nodejitsu
42-
43-
jitsu deploy
44-
45-
*You will now be prompted for a `subdomain` to deploy your application on*
46-
4737
## Available Options:
4838

4939
`-p` Port to use (defaults to 8080)
@@ -69,6 +59,3 @@ This will install `http-server` globally so that it may be run from the command
6959
`-K` or `--key` Path to ssl key file (default: key.pem).
7060

7161
`-h` or `--help` Print this list and exit.
72-
73-
`-c` Set cache time (in seconds) for cache-control max-age header, e.g. -c10 for 10 seconds
74-
(defaults to '3600'). To disable caching, use -c-1.

lib/http-server.js

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
var fs = require('fs'),
22
util = require('util'),
33
union = require('union'),
4-
ecstatic = require('ecstatic');
4+
sexstatic = require('sexstatic'),
5+
ws = require('ws'),
6+
portfinder = require('portfinder'),
7+
chokidar = require('chokidar');
58

69
var HTTPServer = exports.HTTPServer = function (options) {
710
options = options || {};
@@ -19,6 +22,96 @@ var HTTPServer = exports.HTTPServer = function (options) {
1922
}
2023
}
2124

25+
var hotReloadScript = ' \
26+
var xhr = new XMLHttpRequest(); \n \
27+
if (typeof(window.reloadOnChange) == "undefined") \n \
28+
window.reloadOnChange = true; \n \
29+
\n \
30+
xhr.onreadystatechange = function() { \n \
31+
if (xhr.readyState == 4) \n \
32+
{ \n \
33+
var resp = JSON.parse(xhr.responseText); \n \
34+
var changeSocket = new WebSocket("ws://"+location.hostname+":"+resp.port+"/"); \n \
35+
changeSocket.onopen = function() { console.log("-- change socket opened, observing changes --") } \n \
36+
changeSocket.onmessage = function(ev) { \n \
37+
if (ev.data.indexOf("change") != -1) { \n \
38+
setTimeout(function() { \n \
39+
if (window.reloadOnChange) { \n \
40+
console.log("change detected: reloading --"); \n \
41+
window.location.reload(); \n \
42+
}}, 1000); \n \
43+
} \n \
44+
if (ev.data.indexOf("folder") != -1 && document.querySelector("title").innerText.indexOf("Index of") != -1) { \n \
45+
console.log("folder change, reloading"); \n \
46+
window.location.reload(); \n \
47+
} \n \
48+
} \n \
49+
}} \n \
50+
xhr.open("GET", "ws.json", true); \n\
51+
xhr.send(null); \
52+
';
53+
54+
var mutableExtras = {
55+
'http-hot-reload.js': {
56+
'content-type': 'text/javascript',
57+
'content': hotReloadScript
58+
},
59+
'ws.json': {
60+
'content-type': 'text/json',
61+
'content': JSON.stringify({
62+
port: this.wsPort,
63+
path: this.root,
64+
additional: "file untouched. the ws server probably isn't running."
65+
})
66+
}
67+
}
68+
69+
portfinder.basePort = 8086;
70+
portfinder.getPort(function (err, port) {
71+
if (err) { console.log("Error, no open ports available."); console.dir(err); return; }
72+
73+
this.wsPort = port;
74+
console.log('Websocket Server Listening on Port: '+port);
75+
76+
this.wss = new ws.Server({port: port});
77+
this.wss.broadcast = function broadcast(data) {
78+
for(var i in this.clients) {
79+
try { this.clients[i].send(data); } catch (ex) { console.log('error sending to client.'); console.dir(ex); }
80+
}
81+
};
82+
83+
//
84+
85+
mutableExtras['ws.json'].content = JSON.stringify({
86+
port: this.wsPort,
87+
path: this.root
88+
});
89+
90+
var watcher_ready = false;
91+
92+
var watcher = chokidar.watch(this.root, {ignored: /[\/\\]\./, persistent: true});
93+
94+
watcher.on('ready', function() { console.log('Scanned working directory. ready for changes..'); watcher_ready = true; });
95+
watcher.on('unlinkDir', function(path) {
96+
if (!watcher_ready) return;
97+
this.wss.broadcast('folder|'+path);
98+
}.bind(this));
99+
watcher.on('addDir', function(path) {
100+
if (!watcher_ready) return;
101+
this.wss.broadcast('folder|'+path);
102+
}.bind(this));
103+
watcher.on('add', function(path) {
104+
if (!watcher_ready) return;
105+
this.wss.broadcast('folder|'+path);
106+
}.bind(this));
107+
watcher.on('change', function(filename) {
108+
if (!watcher_ready) return;
109+
console.log('change detected! telling clients to reload. ['+filename+']');
110+
this.wss.broadcast('changed|'+filename);
111+
}.bind(this));
112+
}.bind(this));
113+
114+
22115
if (options.headers) {
23116
this.headers = options.headers;
24117
}
@@ -33,6 +126,15 @@ var HTTPServer = exports.HTTPServer = function (options) {
33126
: options.ext;
34127
}
35128

129+
function addReloadScript(src)
130+
{
131+
var index = src.indexOf("</body");
132+
if (index == -1) return src;
133+
var out = src.substr(0, index);
134+
out += '<script type="text/javascript" src="http-hot-reload.js"></script>' + src.substr(index);
135+
return out;
136+
}
137+
36138
var serverOptions = {
37139
before: (options.before || []).concat([
38140
function (req, res) {
@@ -42,13 +144,17 @@ var HTTPServer = exports.HTTPServer = function (options) {
42144

43145
res.emit('next');
44146
},
45-
ecstatic({
147+
sexstatic({
46148
root: this.root,
47149
cache: this.cache,
48150
showDir: this.showDir,
49151
autoIndex: this.autoIndex,
50-
defaultExt: this.ext
51-
})
152+
defaultExt: this.ext,
153+
modifyFunctions: [
154+
addReloadScript
155+
],
156+
extras: mutableExtras
157+
}),
52158
]),
53159
headers: this.headers || {}
54160
};

package.json

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"main": "./lib/http-server",
66
"repository": {
77
"type": "git",
8-
"url": "git://github.com/nodeapps/http-server.git"
8+
"url": "git://github.com/gstack/watch-http-server.git"
99
},
1010
"keywords": [
1111
"cli",
@@ -54,35 +54,40 @@
5454
},
5555
{
5656
"name": "Jinkwon Lee",
57-
"email" : "[email protected]"
57+
"email": "[email protected]"
58+
},
59+
{
60+
"name": "Graham Stachowiak"
5861
}
5962
],
6063
"dependencies": {
64+
"chokidar": "^0.12.4",
6165
"colors": "1.0.3",
66+
"sexstatic": "*",
67+
"opener": "~1.4.0",
6268
"optimist": "0.6.x",
63-
"union": "~0.4.3",
64-
"ecstatic": "~0.5.6",
6569
"portfinder": "0.2.x",
66-
"opener": "~1.4.0"
70+
"union": "~0.4.3",
71+
"ws": "^0.6.3"
6772
},
6873
"devDependencies": {
6974
"vows": "0.7.x",
7075
"request": "2.49.x",
7176
"stylezero": "2.1.1"
7277
},
7378
"bugs": {
74-
"url": "https://github.com/nodeapps/http-server/issues"
79+
"url": "https://github.com/gstack/watch-http-server/issues"
7580
},
7681
"licenses": [
7782
{
7883
"type": "MIT",
79-
"url": "https://github.com/nodeapps/http-server/raw/master/LICENSE"
84+
"url": "https://github.com/gstack/watch-http-server/raw/master/LICENSE"
8085
}
8186
],
8287
"analyze": false,
8388
"preferGlobal": "true",
8489
"bin": {
85-
"http-server": "./bin/http-server",
86-
"hs" : "./bin/http-server"
90+
"watch-http-server": "./bin/http-server",
91+
"whs": "./bin/http-server"
8792
}
8893
}

public/404.html

Lines changed: 0 additions & 10 deletions
This file was deleted.

public/img/turtle.png

-191 KB
Binary file not shown.

public/index.html

Lines changed: 0 additions & 12 deletions
This file was deleted.

screenshots/public.png

-226 KB
Binary file not shown.

0 commit comments

Comments
 (0)