Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'master' into experimental
  • Loading branch information
indexzero committed May 19, 2011
2 parents d3486a6 + 0911c17 commit 8f28618
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 142 deletions.
94 changes: 79 additions & 15 deletions README.md
Expand Up @@ -216,24 +216,56 @@ proxyServerWithForwarding.listen(80);

The forwarding option can be used in conjunction with the proxy table options by simply including both the 'forward' and 'router' properties in the options passed to 'createServer'.

### Using node-http-proxy from the command line
When you install this package with npm, a node-http-proxy binary will become available to you. Using this binary is easy with some simple options:

## Using 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.

### Proxying to HTTP from HTTPS
This is probably the most common use-case for proxying in conjunction with HTTPS. You have some front-facing HTTPS server, but all of your internal traffic is HTTP. In this way, you can reduce the number of servers to which your CA and other important security files are deployed and reduce the computational overhead from HTTPS traffic.

Using HTTPS in `node-http-proxy` is relatively straight-forward:

``` js
usage: node-http-proxy [options]
var fs = require('fs'),
http = require('http'),
https = require('https'),
httpProxy = require('http-proxy');

var options = {
https: {
key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
}
};

All options should be set with the syntax --option=value
//
// Create a standalone HTTPS proxy server
//
httpProxy.createServer(8000, 'localhost', options).listen(8001);

options:
--port PORT Port that the proxy server should run on
--target HOST:PORT Location of the server the proxy will target
--config OUTFILE Location of the configuration file for the proxy server
--silent Silence the log output from the proxy server
-h, --help You're staring at it
//
// Create an instance of HttpProxy to use with another HTTPS server
//
var proxy = new httpProxy.HttpProxy();
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
//
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('hello https\n');
res.end();
}).listen(8000);
```

### 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.
### Proxying to HTTPS from HTTPS
Proxying from HTTPS to HTTPS is essentially the same as proxying from HTTPS to HTTP, but you must include `target` option in when calling `httpProxy.createServer` or instantiating a new instance of `HttpProxy`.

``` js
var fs = require('fs'),
Expand All @@ -244,6 +276,9 @@ var options = {
https: {
key: fs.readFileSync('path/to/your/key.pem', 'utf8'),
cert: fs.readFileSync('path/to/your/cert.pem', 'utf8')
},
target: {
https: true // This could also be an Object with key and cert properties
}
};

Expand All @@ -255,7 +290,12 @@ 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 });
var proxy = new httpProxy.HttpProxy({
target: {
https: true
}
});

https.createServer(options.https, function (req, res) {
proxy.proxyRequest(req, res, {
host: 'localhost',
Expand All @@ -273,7 +313,7 @@ https.createServer(options.https, function (req, res) {
}).listen(8000);
```

### Proxying WebSockets
## 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:

``` js
Expand Down Expand Up @@ -306,16 +346,40 @@ server.on('upgrade', function(req, socket, head) {
});
```

## Using node-http-proxy from the command line
When you install this package with npm, a node-http-proxy binary will become available to you. Using this binary is easy with some simple options:

``` js
usage: node-http-proxy [options]

All options should be set with the syntax --option=value

options:
--port PORT Port that the proxy server should run on
--target HOST:PORT Location of the server the proxy will target
--config OUTFILE Location of the configuration file for the proxy server
--silent Silence the log output from the proxy server
-h, --help You're staring at it
```
<br/>
### Why doesn't node-http-proxy have more advanced features like x, y, or z?
## Why doesn't node-http-proxy have more advanced features like x, y, or z?

If you have a suggestion for a feature currently not supported, feel free to open a [support issue][6]. node-http-proxy is designed to just proxy http requests from one server to another, but we will be soon releasing many other complimentary projects that can be used in conjunction with node-http-proxy.

## Run Tests
The test suite is designed to fully cover the combinatoric possibilities of HTTP and HTTPS proxying:

1. HTTP --> HTTP
2. HTTPS --> HTTP
3. HTTPS --> HTTPS
4. HTTP --> HTTPS

```
vows test/*-test.js --spec
vows test/*-test.js --spec --https
vows test/*-test.js --spec --https --target=https
vows test/*-test.js --spec --target=https
```
<br/>
Expand Down
90 changes: 90 additions & 0 deletions docs/balancing-proxy.html
@@ -0,0 +1,90 @@
<!DOCTYPE html> <html> <head> <title>balancing-proxy.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="balancing-proxy.html"> balancing-proxy.html </a> <a class="source" href="node-http-proxy.html"> node-http-proxy.html </a> <a class="source" href="proxy-table.html"> proxy-table.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> balancing-proxy.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
<span class="cm"> balancing-proxy.js: Transparent Load-Balancing Optimized HTTP Proxy </span>

<span class="cm"> Copyright (c) 2011 Charlie Robbins </span>

<span class="cm"> Permission is hereby granted, free of charge, to any person obtaining</span>
<span class="cm"> a copy of this software and associated documentation files (the</span>
<span class="cm"> &quot;Software&quot;), to deal in the Software without restriction, including</span>
<span class="cm"> without limitation the rights to use, copy, modify, merge, publish,</span>
<span class="cm"> distribute, sublicense, and/or sell copies of the Software, and to</span>
<span class="cm"> permit persons to whom the Software is furnished to do so, subject to</span>
<span class="cm"> the following conditions:</span>

<span class="cm"> The above copyright notice and this permission notice shall be</span>
<span class="cm"> included in all copies or substantial portions of the Software.</span>

<span class="cm"> THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,</span>
<span class="cm"> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF</span>
<span class="cm"> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND</span>
<span class="cm"> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE</span>
<span class="cm"> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION</span>
<span class="cm"> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION</span>
<span class="cm"> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>

<span class="cm">*/</span>

<span class="kd">var</span> <span class="nx">net</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;net&#39;</span><span class="p">),</span>
<span class="nx">HTTPParser</span> <span class="o">=</span> <span class="nx">process</span><span class="p">.</span><span class="nx">binding</span><span class="p">(</span><span class="s1">&#39;http_parser&#39;</span><span class="p">).</span><span class="nx">HTTPParser</span><span class="p">,</span>
<span class="nx">streams</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;morestreams&#39;</span><span class="p">);</span>

<span class="nx">exports</span><span class="p">.</span><span class="nx">createServer</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">),</span>
<span class="nx">callback</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">(),</span>
<span class="nx">options</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">port</span><span class="p">,</span> <span class="nx">host</span><span class="p">,</span> <span class="nx">server</span><span class="p">;</span>

<span class="nx">server</span> <span class="o">=</span> <span class="nx">net</span><span class="p">.</span><span class="nx">createServer</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">socket</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">buffer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">streams</span><span class="p">.</span><span class="nx">BufferedStream</span><span class="p">(),</span>
<span class="nx">parser</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HTTPParser</span><span class="p">(</span><span class="s1">&#39;request&#39;</span><span class="p">);</span>

<span class="nx">parser</span><span class="p">.</span><span class="nx">onHeaderField</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">b</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">len</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">slice</span> <span class="o">=</span> <span class="nx">b</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">start</span> <span class="o">+</span> <span class="nx">len</span><span class="p">).</span><span class="nx">toLowerCase</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">value</span> <span class="o">!=</span> <span class="kc">undefined</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">require</span><span class="p">(</span><span class="s1">&#39;eyes&#39;</span><span class="p">).</span><span class="nx">inspect</span><span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">parser</span><span class="p">.</span><span class="nx">field</span><span class="p">);</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">field</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">field</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">field</span> <span class="o">+=</span> <span class="nx">slice</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">field</span> <span class="o">=</span> <span class="nx">slice</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>

<span class="nx">parser</span><span class="p">.</span><span class="nx">onHeaderValue</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">b</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">len</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">slice</span> <span class="o">=</span> <span class="nx">b</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">start</span> <span class="o">+</span> <span class="nx">len</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">value</span> <span class="o">+=</span> <span class="nx">slice</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">slice</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>

<span class="nx">parser</span><span class="p">.</span><span class="nx">socket</span> <span class="o">=</span> <span class="nx">socket</span><span class="p">;</span>

<span class="nx">socket</span><span class="p">.</span><span class="nx">ondata</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">d</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">end</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">ret</span> <span class="o">=</span> <span class="nx">parser</span><span class="p">.</span><span class="nx">execute</span><span class="p">(</span><span class="nx">d</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">end</span> <span class="o">-</span> <span class="nx">start</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">ret</span><span class="p">);</span>
<span class="p">};</span>

<span class="nx">socket</span><span class="p">.</span><span class="nx">onend</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">ret</span> <span class="o">=</span> <span class="nx">parser</span><span class="p">.</span><span class="nx">finish</span><span class="p">();</span>

<span class="k">if</span> <span class="p">(</span><span class="nx">ret</span> <span class="k">instanceof</span> <span class="nb">Error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">socket</span><span class="p">.</span><span class="nx">destroy</span><span class="p">(</span><span class="nx">ret</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">if</span> <span class="p">(</span><span class="nx">socket</span><span class="p">.</span><span class="nx">writable</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">socket</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">};</span>

<span class="nx">socket</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s1">&#39;hello world&#39;</span><span class="p">);</span>
<span class="nx">socket</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="p">});</span>

<span class="k">return</span> <span class="nx">server</span><span class="p">;</span>
<span class="p">};</span>

</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

0 comments on commit 8f28618

Please sign in to comment.