From 7b82086c91ddddf4894d20199c61452a1f49daad Mon Sep 17 00:00:00 2001 From: Jan Nicklas Date: Tue, 3 Mar 2015 22:05:57 +0100 Subject: [PATCH] Add --proxy setting --- README.md | 2 ++ bin/http-server | 10 ++++++++- lib/http-server.js | 11 +++++++-- package.json | 4 +++- test/http-server-test.js | 48 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 20eb7720e..8d44880b9 100644 --- a/README.md +++ b/README.md @@ -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). diff --git a/bin/http-server b/bin/http-server index 9f7eb6911..04b3c7db9 100755 --- a/bin/http-server +++ b/bin/http-server @@ -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).", @@ -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) { @@ -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) { @@ -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); diff --git a/lib/http-server.js b/lib/http-server.js index 051a239bf..207a06c8a 100644 --- a/lib/http-server.js +++ b/lib/http-server.js @@ -1,7 +1,9 @@ var fs = require('fs'), util = require('util'), union = require('union'), - ecstatic = require('ecstatic'); + ecstatic = require('ecstatic'), + url = require('url'), + proxy = require('proxy-middleware'); var HTTPServer = exports.HTTPServer = function (options) { options = options || {}; @@ -47,12 +49,17 @@ 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') { + serverOptions.before.push(proxy(url.parse(options.proxy))); + } + if (options.https) { serverOptions.https = options.https; } diff --git a/package.json b/package.json index afda5b7dc..dce2cb3ee 100644 --- a/package.json +++ b/package.json @@ -61,8 +61,10 @@ "colors": "1.0.3", "optimist": "0.6.x", "union": "~0.4.3", - "ecstatic": "~0.6.0", + "ecstatic": "~0.6.1", "portfinder": "0.2.x", + "proxy-middleware": "^0.11.0", + "url": "^0.10.2", "opener": "~1.4.0" }, "devDependencies": { diff --git a/test/http-server-test.js b/test/http-server-test.js index 21e0164e0..6efbfb89a 100644 --- a/test/http-server-test.js +++ b/test/http-server-test.js @@ -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);