Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ This will install `http-server` globally so that it may be run from the command

`-o` Open browser window after staring the server

`-P` or `--proxy` Proxies all requests which can't be resolved locally to the given url. e.g.: -P http://someurl.com

`-S` or `--ssl` Enable https.

`-C` or `--cert` Path to ssl cert file (default: cert.pem).
Expand Down
10 changes: 9 additions & 1 deletion bin/http-server
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ if (argv.h || argv.help) {
" -c Cache time (max-age) in seconds [3600], e.g. -c10 for 10 seconds.",
" To disable caching, use -c-1.",
"",
" -P --proxy Fallback proxy if the request cannot be resolved. e.g.: http://someurl.com",
"",
" -S --ssl Enable https.",
" -C --cert Path to ssl cert file (default: cert.pem).",
" -K --key Path to ssl key file (default: key.pem).",
Expand All @@ -37,6 +39,7 @@ var port = argv.p || parseInt(process.env.PORT, 10),
host = argv.a || '0.0.0.0',
log = (argv.s || argv.silent) ? (function () {}) : console.log,
ssl = !!argv.S || !!argv.ssl,
proxy = argv.P || argv.proxy,
requestLogger;

if (!argv.s && !argv.silent) {
Expand All @@ -62,7 +65,8 @@ function listen(port) {
showDir: argv.d,
autoIndex: argv.i,
ext: argv.e || argv.ext,
logFn: requestLogger
logFn: requestLogger,
proxy: proxy
};

if (argv.cors) {
Expand All @@ -88,6 +92,10 @@ function listen(port) {
+ ' on: '.yellow
+ uri.cyan);

if (typeof proxy === 'string') {
log('Unhandled requests will be served from: ' + proxy);
}

log('Hit CTRL-C to stop the server');
if (argv.o) {
opener(uri);
Expand Down
16 changes: 14 additions & 2 deletions lib/http-server.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var fs = require('fs'),
util = require('util'),
union = require('union'),
ecstatic = require('ecstatic');
ecstatic = require('ecstatic'),
httpProxy = require('http-proxy');

var HTTPServer = exports.HTTPServer = function (options) {
options = options || {};
Expand Down Expand Up @@ -47,12 +48,23 @@ var HTTPServer = exports.HTTPServer = function (options) {
cache: this.cache,
showDir: this.showDir,
autoIndex: this.autoIndex,
defaultExt: this.ext
defaultExt: this.ext,
handleError: typeof options.proxy !== 'string'
})
]),
headers: this.headers || {}
};

if (typeof options.proxy === 'string') {
var proxy = httpProxy.createProxyServer({});
serverOptions.before.push(function (req, res) {
proxy.web(req, res, {
target: options.proxy,
changeOrigin: true
});
});
}

if (options.https) {
serverOptions.https = options.https;
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
"colors": "1.0.3",
"optimist": "0.6.x",
"union": "~0.4.3",
"ecstatic": "~0.6.0",
"ecstatic": "~0.6.1",
"http-proxy": "^1.8.1",
"portfinder": "0.2.x",
"opener": "~1.4.0"
},
Expand Down
48 changes: 48 additions & 0 deletions test/http-server-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,54 @@ vows.describe('http-server').addBatch({
assert.equal(res.headers['access-control-allow-origin'], '*');
assert.equal(res.headers['access-control-allow-credentials'], 'true');
}
},
'When http-server is proxying from 8081 to 8080': {
topic: function () {
var proxyServer = httpServer.createServer({
proxy: 'http://127.0.0.1:8080/',
root: path.join(__dirname, 'fixtures')
});
proxyServer.listen(8081);
this.callback(null, proxyServer);
},
'it should serve files from the proxy server root directory': {
topic: function () {
request('http://127.0.0.1:8081/root/file', this.callback);
},
'status code should be the enpoint code 200': function (res) {
assert.equal(res.statusCode, 200);
},
'and file content': {
topic: function (res, body) {
var self = this;
fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) {
self.callback(err, data, body);
});
},
'should match content of the served file': function (err, file, body) {
assert.equal(body.trim(), file.trim());
}
}
},
'it should fallback to the proxied server': {
topic: function () {
request('http://127.0.0.1:8081/file', this.callback);
},
'status code should be the enpoint code 200': function (res) {
assert.equal(res.statusCode, 200);
},
'and file content': {
topic: function (res, body) {
var self = this;
fs.readFile(path.join(root, 'file'), 'utf8', function (err, data) {
self.callback(err, data, body);
});
},
'should match content of the proxied served file': function (err, file, body) {
assert.equal(body.trim(), file.trim());
}
}
}
}
}
}).export(module);