From 212009df6b08de3c0c97a4e9ec43f60f6bf49ea6 Mon Sep 17 00:00:00 2001 From: indexzero Date: Sun, 17 Apr 2011 03:11:06 -0400 Subject: [PATCH] [doc api] Update README.md and CHANGELOG.md for v0.5.0. Update bin/node-http-proxy to read files specified in `config.https` --- CHANGELOG.md | 7 +- README.md | 118 ++++++++++++++++++++++++++++++---- bin/node-http-proxy | 9 +++ examples/basic-proxy-https.js | 2 +- examples/basic-proxy.js | 14 +++- examples/forward-proxy.js | 4 +- examples/latent-proxy.js | 2 +- examples/proxy-table.js | 2 +- examples/standalone-proxy.js | 2 +- lib/node-http-proxy.js | 2 +- test/helpers.js | 2 +- 11 files changed, 141 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc2bae..850453e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ ## Version 0.5.0 - 4/15/2011 - Remove winston in favor of custom events (indexzero) - +- Add x-forwarded-for Header (indexzero) +- Fix WebSocket support (indexzero) +- Add tests / examples for WebSocket support (indexzero) +- Update .proxyRequest() and .proxyWebSocketRequest() APIs (indexzero) +- Add HTTPS support (indexzero) +- Add tests / examples for HTTPS support (indexzero) ## Version 0.4.1 - 3/20/2011 - Include missing dependency in package.json (indexzero) diff --git a/README.md b/README.md index fc941ec..509b417 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# node-http-proxy - v0.4.1 +# node-http-proxy - v0.5.0 - + ## Battle-hardened node.js http proxy @@ -10,6 +10,8 @@ * Can be used as a CommonJS module in node.js * Uses event buffering to support application latency in proxied requests * Reverse or Forward Proxy based on simple JSON-based configuration +* Supports [WebSockets][1] +* Supports [HTTPS][2] * Minimal request overhead and latency * Full suite of functional tests * Battled-hardened through __production usage__ @ [nodejitsu.com][0] @@ -40,7 +42,13 @@ There are several ways to use node-http-proxy; the library is designed to be fle 4. As a forward-proxy with a reverse proxy 5. From the command-line as a long running process -See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js) for further examples. +In each of these scenarios node-http-proxy can handle any of these types of requests: + +1. HTTP Requests (http://) +2. HTTPS Requests (https://) +3. WebSocket Requests (ws://) + +See the [examples][3] for more working sample code. ### Setup a basic stand-alone proxy server
@@ -55,7 +63,7 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
   // Create your target server
   //
   http.createServer(function (req, res) {
-    res.writeHead(200, {'Content-Type': 'text/plain'});
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
     res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
     res.end();
   }).listen(9000);
@@ -73,11 +81,14 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
     //
     // Put your custom server logic here
     //
-    proxy.proxyRequest(req, res, 9000, 'localhost');
+    proxy.proxyRequest(req, res, {
+      host: 'localhost',
+      port: 9000
+    });
   }).listen(8000);
 
   http.createServer(function (req, res) {
-    res.writeHead(200, {'Content-Type': 'text/plain'});
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
     res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
     res.end();
   }).listen(9000);
@@ -103,12 +114,16 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
     // performing async actions before proxying a request
     //
     setTimeout(function () {
-      proxy.proxyRequest(req, res, 9000, 'localhost', buffer);      
+      proxy.proxyRequest(req, res, {
+        host: 'localhost',
+        port: 9000, 
+        buffer: buffer
+      });      
     }, 2000);
   }).listen(8000);
 
   http.createServer(function (req, res) {
-    res.writeHead(200, {'Content-Type': 'text/plain'});
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
     res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
     res.end();
   }).listen(9000);
@@ -131,11 +146,14 @@ See the [demo](http://github.com/nodejitsu/node-http-proxy/blob/master/demo.js)
     //
     // Put your custom server logic here, then proxy
     //
-    proxy.proxyRequest(req, res, 9000, 'localhost');
+    proxy.proxyRequest(req, res, {
+      host: 'localhost',
+      port: 9000
+    });
   }).listen(8001);
 
   http.createServer(function (req, res) {
-    res.writeHead(200, {'Content-Type': 'text/plain'});
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
     res.write('request successfully proxied: ' + req.url +'\n' + JSON.stringify(req.headers, true, 2));
     res.end();
   }).listen(9000); 
@@ -172,7 +190,7 @@ As mentioned in the previous section, all routes passes to the ProxyTable are by
   }
 
-Notice here that I have not included paths on the individual domains because this is not possible when using only the HTTP 'Host' header. Care to learn more? See [RFC2616: HTTP/1.1, Section 14.23, "Host"][1]. +Notice here that I have not included paths on the individual domains because this is not possible when using only the HTTP 'Host' header. Care to learn more? See [RFC2616: HTTP/1.1, Section 14.23, "Host"][4]. ### Proxy requests with an additional forward proxy Sometimes in addition to a reverse proxy, you may want your front-facing server to forward traffic to another location. For example, if you wanted to load test your staging environment. This is possible when using node-http-proxy using similar JSON-based configuration to a proxy table: @@ -203,6 +221,78 @@ When you install this package with npm, a node-http-proxy binary will become ava -h, --help You're staring at it +### Proxying over HTTPS +You have all the full flexibility of node-http-proxy offers in HTTPS as well as HTTP. The two basic scenarios are: with a stand-alone proxy server or in conjunction with another HTTPS server. +
+  var fs = require('fs'),
+      https = require('https'),
+      httpProxy = require('httpProxy');
+      
+  var options = {
+    https: {
+      key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
+      cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
+    }
+  };
+  
+  //
+  // Create a standalone HTTPS proxy server
+  //
+  httpProxy.createServer(8000, 'localhost', options).listen(8001);
+  
+  //
+  // Create an instance of HttpProxy to use with another HTTPS server
+  //
+  var proxy = new httpProxy.HttpProxy({ https: true });
+  https.createServer(options.https, function (req, res) {
+    proxy.proxyRequest(req, res, {
+      host: 'localhost', 
+      port: 8000
+    })
+  }).listen(8002);
+  
+  //
+  // Create the target HTTPS server for both cases
+  //
+  https.createServer(options.https, function (req, res) {
+    res.writeHead(200, { 'Content-Type': 'text/plain' });
+    res.write('hello https\n');
+  	res.end();
+  }).listen(8000);
+
+ +### Proxying WebSockets +Websockets are handled automatically when using the `httpProxy.createServer()`, but if you want to use it in conjunction with a stand-alone HTTP + WebSocket (such as [socket.io][5]) server here's how: +
+  var http = require('http'),
+      httpProxy = require('httpProxy');
+      
+  //
+  // Create an instance of node-http-proxy
+  //
+  var proxy = new httpProxy.HttpProxy();
+  
+  var server = http.createServer(function (req, res) {
+    //
+    // Proxy normal HTTP requests
+    //
+    proxy.proxyRequest(req, res, {
+      host: 'localhost',
+      port: 8000
+    })
+  });
+  
+  server.on('upgrade', function(req, socket, head) {
+    //
+    // Proxy websocket requests too
+    //
+    proxy.proxyWebSocketRequest(req, socket, head, {
+      host: 'localhost',
+      port: 8000
+    });
+  });
+
+
### Why doesn't node-http-proxy have more advanced features like x, y, or z? @@ -235,4 +325,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [0]: http://nodejitsu.com -[1]: http://www.ietf.org/rfc/rfc2616.txt \ No newline at end of file +[1]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/web-socket-proxy.js +[2]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/basic-proxy-https.js +[3]: https://github.com/nodejitsu/node-http-proxy/tree/v0.5.0/examples +[4]: http://www.ietf.org/rfc/rfc2616.txt +[5]: http://socket.io \ No newline at end of file diff --git a/bin/node-http-proxy b/bin/node-http-proxy index ad2b24c..7c0f4f8 100755 --- a/bin/node-http-proxy +++ b/bin/node-http-proxy @@ -40,6 +40,15 @@ if (argv.config) { } } +// +// If `config.https` is set, then load those files into the config options. +// +if (options.config) { + Object.keys(options.config).forEach(function (key) { + options.config[key] = fs.readFileSync(options.config[key], 'utf8'); + }); +} + // // Check to see if we should silence the logs // diff --git a/examples/basic-proxy-https.js b/examples/basic-proxy-https.js index 69f9fdc..9d1a4a2 100644 --- a/examples/basic-proxy-https.js +++ b/examples/basic-proxy-https.js @@ -37,7 +37,7 @@ var opts = helpers.loadHttps(); // Crete the target HTTPS server // https.createServer(opts, function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('hello https\n'); res.end(); }).listen(8000); diff --git a/examples/basic-proxy.js b/examples/basic-proxy.js index 664e79b..1c1000e 100644 --- a/examples/basic-proxy.js +++ b/examples/basic-proxy.js @@ -28,7 +28,17 @@ var util = require('util'), colors = require('colors') http = require('http'), httpProxy = require('./../lib/node-http-proxy'); - + +// ascii art from http://github.com/marak/asciimo +var welcome = '\ +# # ##### ##### ##### ##### ##### #### # # # # \n\ +# # # # # # # # # # # # # # # # \n\ +###### # # # # ##### # # # # # # ## # \n\ +# # # # ##### ##### ##### # # ## # \n\ +# # # # # # # # # # # # # \n\ +# # # # # # # # #### # # # \n'; +util.puts(welcome.rainbow.bold); + // // Basic Http Proxy Server // @@ -38,7 +48,7 @@ httpProxy.createServer(9000, 'localhost').listen(8000); // Target Http Server // http.createServer(function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.end(); }).listen(9000); diff --git a/examples/forward-proxy.js b/examples/forward-proxy.js index 1c0a547..8a43dad 100644 --- a/examples/forward-proxy.js +++ b/examples/forward-proxy.js @@ -43,7 +43,7 @@ httpProxy.createServer(9000, 'localhost', { // Target Http Server // http.createServer(function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.end(); }).listen(9000); @@ -53,7 +53,7 @@ http.createServer(function (req, res) { // http.createServer(function (req, res) { util.puts('Receiving forward for: ' + req.url) - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('request successfully forwarded to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.end(); }).listen(9001); diff --git a/examples/latent-proxy.js b/examples/latent-proxy.js index 2de9fab..aea2392 100644 --- a/examples/latent-proxy.js +++ b/examples/latent-proxy.js @@ -47,7 +47,7 @@ httpProxy.createServer(function (req, res, proxy) { // Target Http Server // http.createServer(function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.end(); }).listen(9000); diff --git a/examples/proxy-table.js b/examples/proxy-table.js index 822bd83..a3817a2 100644 --- a/examples/proxy-table.js +++ b/examples/proxy-table.js @@ -42,7 +42,7 @@ httpProxy.createServer({ // Target Http Server // http.createServer(function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.end(); }).listen(9000); diff --git a/examples/standalone-proxy.js b/examples/standalone-proxy.js index 0b19e69..9cab8c0 100644 --- a/examples/standalone-proxy.js +++ b/examples/standalone-proxy.js @@ -48,7 +48,7 @@ http.createServer(function (req, res) { // Target Http Server // http.createServer(function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.end(); }).listen(9000); diff --git a/lib/node-http-proxy.js b/lib/node-http-proxy.js index 902ddd2..698b80a 100644 --- a/lib/node-http-proxy.js +++ b/lib/node-http-proxy.js @@ -192,7 +192,7 @@ exports.createServer = function () { // Set the proxy on the server so it is available // to the consumer of the server // - //server.proxy = proxy; + server.proxy = proxy; return server; }; diff --git a/test/helpers.js b/test/helpers.js index defcd8b..598a426 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -198,7 +198,7 @@ TestRunner.prototype.startProxyServerWithForwarding = function (port, targetPort // TestRunner.prototype.startTargetServer = function (port, output, callback) { var that = this, targetServer, handler = function (req, res) { - res.writeHead(200, {'Content-Type': 'text/plain'}); + res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write(output); res.end(); };