mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
[doc api test] Wrap things up for v0.4.0 release: Add hostnameOnly routing to ProxyTable, add more documentation, fix edge-cases until they can be further investigated in node.js core
This commit is contained in:
parent
4110448046
commit
571531820e
46
README.md
46
README.md
@ -1,4 +1,4 @@
|
||||
# node-http-proxy - v0.3.1
|
||||
# node-http-proxy - v0.4.0
|
||||
|
||||
<img src = "http://i.imgur.com/dSSUX.png"/>
|
||||
|
||||
@ -6,16 +6,15 @@
|
||||
|
||||
### Features
|
||||
|
||||
- reverse-proxies incoming http.Server requests
|
||||
- can be used as a CommonJS module in node.js
|
||||
- uses event buffering to support application latency in proxied requests
|
||||
- can proxy based on simple JSON-based configuration
|
||||
- forward proxying based on simple JSON-based configuration
|
||||
- minimal request overhead and latency
|
||||
- fully-tested
|
||||
- battled-hardened through production usage @ [nodejitsu.com][0]
|
||||
- written entirely in javascript
|
||||
- easy to use api
|
||||
* Reverse proxies incoming http.ServerRequest streams
|
||||
* 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
|
||||
* Minimal request overhead and latency
|
||||
* Full suite of functional tests
|
||||
* Battled-hardened through __production usage__ @ [nodejitsu.com][0]
|
||||
* Written entirely in Javascript
|
||||
* Easy to use API
|
||||
|
||||
### When to use node-http-proxy
|
||||
|
||||
@ -147,18 +146,34 @@ A Proxy Table is a simple lookup table that maps incoming requests to proxy targ
|
||||
<pre>
|
||||
var options = {
|
||||
router: {
|
||||
'foo.com': '127.0.0.1:8001',
|
||||
'bar.com': '127.0.0.1:8002'
|
||||
'foo.com/baz': '127.0.0.1:8001',
|
||||
'foo.com/buz': '127.0.0.1:8002',
|
||||
'bar.com/buz': '127.0.0.1:8003'
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
|
||||
The above route table will take incoming requests to 'foo.com' and forward them to '127.0.0.1:8001'. Likewise it will take incoming requests to 'bar.com' and forward them to '127.0.0.1:8002'. The routes themselves are later converted to regular expressions to enable more complex matching functionality. We can create a proxy server with these options by using the following code:
|
||||
The above route table will take incoming requests to 'foo.com/baz' and forward them to '127.0.0.1:8001'. Likewise it will take incoming requests to 'foo.com/buz' and forward them to '127.0.0.1:8002'. The routes themselves are later converted to regular expressions to enable more complex matching functionality. We can create a proxy server with these options by using the following code:
|
||||
<pre>
|
||||
var proxyServer = httpProxy.createServer(options);
|
||||
proxyServer.listen(80);
|
||||
</pre>
|
||||
|
||||
### Proxy requests using a 'Hostname Only' ProxyTable
|
||||
As mentioned in the previous section, all routes passes to the ProxyTable are by default converted to regular expressions that are evaluated at proxy-time. This is good for complex URL rewriting of proxy requests, but less efficient when one simply wants to do pure hostname routing based on the HTTP 'Host' header. If you are only concerned with hostname routing, you change the lookup used by the internal ProxyTable:
|
||||
|
||||
<pre>
|
||||
var options = {
|
||||
hostnameOnly, true,
|
||||
router: {
|
||||
'foo.com': '127.0.0.1:8001',
|
||||
'bar.com': '127.0.0.1:8002'
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
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].
|
||||
|
||||
### 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:
|
||||
<pre>
|
||||
@ -219,4 +234,5 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
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
|
||||
[0]: http://nodejitsu.com
|
||||
[1]: http://www.ietf.org/rfc/rfc2616.txt
|
||||
@ -148,7 +148,7 @@ for managing the life-cycle of streaming reverse proxyied HTTP requests.</p>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">router</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">proxyTable</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ProxyTable</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">router</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">silent</span> <span class="o">||</span> <span class="kc">false</span><span class="p">);</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">proxyTable</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ProxyTable</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">router</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">silent</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">hostnameOnly</span><span class="p">);</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">proxyTable</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'routes'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">routes</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'routes'</span><span class="p">,</span> <span class="nx">routes</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
@ -157,7 +157,7 @@ for managing the life-cycle of streaming reverse proxyied HTTP requests.</p>
|
||||
|
||||
<h4>@obj {Object} Object to pause events from</h4>
|
||||
|
||||
<p>Pause <code>data</code> and <code>end</code> events on the given <code>obj</code>.
|
||||
<p>Buffer <code>data</code> and <code>end</code> events from the given <code>obj</code>.
|
||||
Consumers of HttpProxy performing async tasks
|
||||
<strong>must</strong> utilize this utility, to re-emit data once
|
||||
the async operation has completed, otherwise these
|
||||
@ -239,8 +239,12 @@ specified request to the address provided in <code>this.options.forward</code></
|
||||
<span class="nx">winston</span><span class="p">.</span><span class="nx">verbose</span><span class="p">(</span><span class="s1">'Forwarding HTTP request to: '</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">forward</span><span class="p">.</span><span class="nx">host</span> <span class="o">+</span> <span class="s1">':'</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">forward</span><span class="p">.</span><span class="nx">port</span><span class="p">);</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">_forwardRequest</span><span class="p">(</span><span class="nx">req</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="kd">function</span> <span class="nx">proxyError</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
</pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <h4>function proxyError (err)</h4>
|
||||
|
||||
<h4>@err {Error} Error contacting the proxy target</h4>
|
||||
|
||||
<p>Short-circuits <code>res</code> in the event of any error when
|
||||
contacting the proxy target at <code>host</code> / <code>port</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">proxyError</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">errState</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
||||
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="p">{</span> <span class="s1">'Content-Type'</span><span class="o">:</span> <span class="s1">'text/plain'</span> <span class="p">});</span>
|
||||
|
||||
@ -250,7 +254,7 @@ specified request to the address provided in <code>this.options.forward</code></
|
||||
|
||||
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverseProxy</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">request</span><span class="p">({</span>
|
||||
</pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverseProxy</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">request</span><span class="p">({</span>
|
||||
<span class="nx">host</span><span class="o">:</span> <span class="nx">host</span><span class="p">,</span>
|
||||
<span class="nx">port</span><span class="o">:</span> <span class="nx">port</span><span class="p">,</span>
|
||||
<span class="nx">agent</span><span class="o">:</span> <span class="nx">_getAgent</span><span class="p">(</span><span class="nx">host</span><span class="p">,</span> <span class="nx">port</span><span class="p">),</span>
|
||||
@ -258,37 +262,50 @@ specified request to the address provided in <code>this.options.forward</code></
|
||||
<span class="nx">path</span><span class="o">:</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
||||
<span class="nx">headers</span><span class="o">:</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span>
|
||||
<span class="p">},</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
|
||||
</pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Process the reverseProxy response when it's received.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">connection</span><span class="p">)</span> <span class="p">{</span>
|
||||
</pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Process the <code>reverseProxy</code> <code>response</code> when it's received.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">connection</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">connection</span><span class="p">)</span> <span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">connection</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">connection</span><span class="p">;</span>
|
||||
<span class="k">else</span> <span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">connection</span> <span class="o">=</span> <span class="s1">'close'</span><span class="p">;</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Set the response headers of the client response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">statusCode</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>Status code = 304
|
||||
No 'data' event and no 'end'</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">statusCode</span> <span class="o">===</span> <span class="mi">304</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>Set the headers of the client response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">statusCode</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p><code>response.statusCode === 304</code>: No 'data' event and no 'end'</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">statusCode</span> <span class="o">===</span> <span class="mi">304</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>Add event handler for the proxied response in chunks</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">response</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>For each data <code>chunk</code> received from the <code>reverseProxy</code>
|
||||
<code>response</code> write it to the outgoing <code>res</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">response</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">method</span> <span class="o">!==</span> <span class="s1">'HEAD'</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">res</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">chunk</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Add event listener for end of proxied response</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">response</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>When the <code>reverseProxy</code> <code>response</code> ends, end the
|
||||
corresponding outgoing <code>res</code> unless we have entered
|
||||
an error state. In which case, assume <code>res.end()</code> has
|
||||
already been called and the 'error' event listener
|
||||
removed.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">response</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">errState</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">reverseProxy</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">proxyError</span><span class="p">);</span>
|
||||
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
</pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Add a listener for the connection timeout event</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverseProxy</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">proxyError</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Chunk the client request body as chunks from the proxied request come in</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
||||
</pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Handle 'error' events from the <code>reverseProxy</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverseProxy</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">proxyError</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>For each data <code>chunk</code> received from the incoming
|
||||
<code>req</code> write it to the <code>reverseProxy</code> request.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">errState</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">reverseProxy</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">chunk</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>At the end of the client request, we are going to stop the proxied request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">errState</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>When the incoming <code>req</code> ends, end the corresponding <code>reverseProxy</code>
|
||||
request unless we have entered an error state. </p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p><strong>Remark</strong> <em>(indexzero | 3/10/2011)</em>: This is a short-term workaround for a suspect error from net.js when
|
||||
<code>http.ClientRequest.end()</code> is called in reproducable, but uninvestigated scenarios </p>
|
||||
|
||||
<pre><code>net.js:313
|
||||
throw new Error('Socket.end() called already; cannot write.');
|
||||
^
|
||||
Error: Socket.end() called already; cannot write.
|
||||
at Socket.write (net.js:313:13)
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">errState</span> <span class="cm">/*&& (!reverseProxy.socket || reverseProxy.socket._writeQueueLast() !== 42)*/</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">reverseProxy</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>If we have been passed buffered data, resume it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">buffer</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">errState</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>If we have been passed buffered data, resume it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">buffer</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">errState</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">buffer</span><span class="p">.</span><span class="nx">resume</span><span class="p">();</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">};</span>
|
||||
</pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <h3>@private function _forwardRequest (req)</h3>
|
||||
</pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <h3>@private function _forwardRequest (req)</h3>
|
||||
|
||||
<h4>@req {ServerRequest} Incoming HTTP Request to proxy.</h4>
|
||||
|
||||
@ -298,36 +315,36 @@ by <code>this.options.forward</code> ignoring errors and the subsequent response
|
||||
|
||||
<span class="nx">port</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">forward</span><span class="p">.</span><span class="nx">port</span><span class="p">;</span>
|
||||
<span class="nx">host</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">forward</span><span class="p">.</span><span class="nx">host</span><span class="p">;</span>
|
||||
</pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">forwardProxy</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">request</span><span class="p">({</span>
|
||||
</pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">forwardProxy</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">request</span><span class="p">({</span>
|
||||
<span class="nx">host</span><span class="o">:</span> <span class="nx">host</span><span class="p">,</span>
|
||||
<span class="nx">port</span><span class="o">:</span> <span class="nx">port</span><span class="p">,</span>
|
||||
<span class="nx">agent</span><span class="o">:</span> <span class="nx">_getAgent</span><span class="p">(</span><span class="nx">host</span><span class="p">,</span> <span class="nx">port</span><span class="p">),</span>
|
||||
<span class="nx">method</span><span class="o">:</span> <span class="nx">req</span><span class="p">.</span><span class="nx">method</span><span class="p">,</span>
|
||||
<span class="nx">path</span><span class="o">:</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
|
||||
<span class="nx">headers</span><span class="o">:</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span>
|
||||
<span class="p">},</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy.
|
||||
<span class="p">},</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</a> </div> <p>Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy.
|
||||
Remark (indexzero): We will eventually emit a 'forward' event here for performance tuning.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">});</span>
|
||||
</pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>Add a listener for the connection timeout event.</p>
|
||||
</pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</a> </div> <p>Add a listener for the connection timeout event.</p>
|
||||
|
||||
<p>Remark: Ignoring this error in the event
|
||||
forward target doesn't exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">forwardProxy</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span> <span class="p">});</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</a> </div> <p>Chunk the client request body as chunks from the proxied request come in</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
||||
forward target doesn't exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">forwardProxy</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span> <span class="p">});</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</a> </div> <p>Chunk the client request body as chunks from the proxied request come in</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">chunk</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">forwardProxy</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">chunk</span><span class="p">);</span>
|
||||
<span class="p">})</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</a> </div> <p>At the end of the client request, we are going to stop the proxied request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="p">})</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>At the end of the client request, we are going to stop the proxied request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">forwardProxy</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">HttpProxy</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">proxyWebSocketRequest</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">port</span><span class="p">,</span> <span class="nx">server</span><span class="p">,</span> <span class="nx">host</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span> <span class="nx">req</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">req</span><span class="p">,</span> <span class="nx">socket</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">sock</span><span class="p">,</span> <span class="nx">head</span> <span class="o">=</span> <span class="nx">self</span><span class="p">.</span><span class="nx">head</span><span class="p">,</span>
|
||||
<span class="nx">headers</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">_headers</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">),</span> <span class="nx">CRLF</span> <span class="o">=</span> <span class="s1">'\r\n'</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</a> </div> <p>Will generate clone of headers
|
||||
<span class="nx">headers</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">_headers</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">),</span> <span class="nx">CRLF</span> <span class="o">=</span> <span class="s1">'\r\n'</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</a> </div> <p>Will generate clone of headers
|
||||
To not change original</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">_headers</span><span class="p">(</span><span class="nx">headers</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">h</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">headers</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">h</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">headers</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">return</span> <span class="nx">h</span><span class="p">;</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>WebSocket requests has method = GET</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">method</span> <span class="o">!==</span> <span class="s1">'GET'</span> <span class="o">||</span> <span class="nx">headers</span><span class="p">.</span><span class="nx">upgrade</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">()</span> <span class="o">!==</span> <span class="s1">'websocket'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</a> </div> <p>This request is not WebSocket request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span><span class="p">;</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</a> </div> <p>Turn of all bufferings
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</a> </div> <p>WebSocket requests has method = GET</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">method</span> <span class="o">!==</span> <span class="s1">'GET'</span> <span class="o">||</span> <span class="nx">headers</span><span class="p">.</span><span class="nx">upgrade</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">()</span> <span class="o">!==</span> <span class="s1">'websocket'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>This request is not WebSocket request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span><span class="p">;</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>Turn of all bufferings
|
||||
For server set KeepAlive
|
||||
For client set encoding</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">_socket</span><span class="p">(</span><span class="nx">socket</span><span class="p">,</span> <span class="nx">server</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">setTimeout</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
|
||||
@ -338,20 +355,20 @@ For client set encoding</p> </td> <td class="code">
|
||||
<span class="k">else</span> <span class="p">{</span>
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">setEncoding</span><span class="p">(</span><span class="s1">'utf8'</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>Client socket</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_socket</span><span class="p">(</span><span class="nx">socket</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>If host is undefined
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>Client socket</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_socket</span><span class="p">(</span><span class="nx">socket</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>If host is undefined
|
||||
Get it from headers</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">host</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">host</span> <span class="o">=</span> <span class="nx">headers</span><span class="p">.</span><span class="nx">Host</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>Remote host address</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">remote_host</span> <span class="o">=</span> <span class="nx">server</span> <span class="o">+</span> <span class="p">(</span><span class="nx">port</span> <span class="o">-</span> <span class="mi">80</span> <span class="o">===</span> <span class="mi">0</span> <span class="o">?</span> <span class="s1">''</span> <span class="o">:</span> <span class="s1">':'</span> <span class="o">+</span> <span class="nx">port</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>Change headers</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">headers</span><span class="p">.</span><span class="nx">Host</span> <span class="o">=</span> <span class="nx">remote_host</span><span class="p">;</span>
|
||||
<span class="nx">headers</span><span class="p">.</span><span class="nx">Origin</span> <span class="o">=</span> <span class="s1">'http://'</span> <span class="o">+</span> <span class="nx">remote_host</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>Open request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="nx">manager</span><span class="p">.</span><span class="nx">getPool</span><span class="p">(</span><span class="nx">port</span><span class="p">,</span> <span class="nx">server</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>Remote host address</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">remote_host</span> <span class="o">=</span> <span class="nx">server</span> <span class="o">+</span> <span class="p">(</span><span class="nx">port</span> <span class="o">-</span> <span class="mi">80</span> <span class="o">===</span> <span class="mi">0</span> <span class="o">?</span> <span class="s1">''</span> <span class="o">:</span> <span class="s1">':'</span> <span class="o">+</span> <span class="nx">port</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>Change headers</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">headers</span><span class="p">.</span><span class="nx">Host</span> <span class="o">=</span> <span class="nx">remote_host</span><span class="p">;</span>
|
||||
<span class="nx">headers</span><span class="p">.</span><span class="nx">Origin</span> <span class="o">=</span> <span class="s1">'http://'</span> <span class="o">+</span> <span class="nx">remote_host</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</a> </div> <p>Open request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="nx">manager</span><span class="p">.</span><span class="nx">getPool</span><span class="p">(</span><span class="nx">port</span><span class="p">,</span> <span class="nx">server</span><span class="p">);</span>
|
||||
|
||||
<span class="nx">p</span><span class="p">.</span><span class="nx">getClient</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">client</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>Based on 'pool/main.js'</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">client</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="s1">'GET'</span><span class="p">,</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">headers</span><span class="p">);</span>
|
||||
<span class="nx">p</span><span class="p">.</span><span class="nx">getClient</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">client</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</a> </div> <p>Based on 'pool/main.js'</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">client</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="s1">'GET'</span><span class="p">,</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span> <span class="nx">headers</span><span class="p">);</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">errorListener</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">client</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">errorListener</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</a> </div> <p>Remove the client from the pool's available clients since it has errored</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">p</span><span class="p">.</span><span class="nx">clients</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">clients</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">client</span><span class="p">),</span> <span class="mi">1</span><span class="p">);</span>
|
||||
</pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</a> </div> <p>Remove the client from the pool's available clients since it has errored</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">p</span><span class="p">.</span><span class="nx">clients</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">clients</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">client</span><span class="p">),</span> <span class="mi">1</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></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</a> </div> <p>Not disconnect on update</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">client</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'upgrade'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">remote_socket</span><span class="p">,</span> <span class="nx">head</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</a> </div> <p>Prepare socket</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_socket</span><span class="p">(</span><span class="nx">remote_socket</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>Emit event</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">onUpgrade</span><span class="p">(</span><span class="nx">remote_socket</span><span class="p">);</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>Not disconnect on update</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">client</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'upgrade'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">remote_socket</span><span class="p">,</span> <span class="nx">head</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>Prepare socket</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_socket</span><span class="p">(</span><span class="nx">remote_socket</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>Emit event</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">onUpgrade</span><span class="p">(</span><span class="nx">remote_socket</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
|
||||
<span class="nx">client</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="nx">errorListener</span><span class="p">);</span>
|
||||
@ -365,23 +382,23 @@ Get it from headers</p> </td> <td class="code">
|
||||
<span class="nx">client</span><span class="p">.</span><span class="nx">busy</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">handshake</span><span class="p">;</span>
|
||||
<span class="nx">request</span><span class="p">.</span><span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">handshake</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>Handshaking</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>Ok, kind of harmfull part of code
|
||||
<span class="nx">request</span><span class="p">.</span><span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">handshake</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</a> </div> <p>Handshaking</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p>Ok, kind of harmfull part of code
|
||||
Socket.IO is sending hash at the end of handshake
|
||||
If protocol = 76
|
||||
But we need to replace 'host' and 'origin' in response
|
||||
So we split data to printable data and to non-printable
|
||||
(Non-printable will come after double-CRLF)</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">sdata</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</a> </div> <p>Get Printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">sdata</span> <span class="o">=</span> <span class="nx">sdata</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">sdata</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="nx">CRLF</span> <span class="o">+</span> <span class="nx">CRLF</span><span class="p">));</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p>Get Non-Printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">data</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">Buffer</span><span class="p">.</span><span class="nx">byteLength</span><span class="p">(</span><span class="nx">sdata</span><span class="p">),</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>Replace host and origin</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">sdata</span> <span class="o">=</span> <span class="nx">sdata</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">remote_host</span><span class="p">,</span> <span class="nx">host</span><span class="p">)</span>
|
||||
(Non-printable will come after double-CRLF)</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">sdata</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>Get Printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">sdata</span> <span class="o">=</span> <span class="nx">sdata</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">sdata</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="nx">CRLF</span> <span class="o">+</span> <span class="nx">CRLF</span><span class="p">));</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>Get Non-Printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">data</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">Buffer</span><span class="p">.</span><span class="nx">byteLength</span><span class="p">(</span><span class="nx">sdata</span><span class="p">),</span> <span class="nx">data</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</a> </div> <p>Replace host and origin</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">sdata</span> <span class="o">=</span> <span class="nx">sdata</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">remote_host</span><span class="p">,</span> <span class="nx">host</span><span class="p">)</span>
|
||||
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">remote_host</span><span class="p">,</span> <span class="nx">host</span><span class="p">);</span>
|
||||
|
||||
<span class="k">try</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>Write printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">socket</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">sdata</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</a> </div> <p>Write non-printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">socket</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
|
||||
<span class="k">try</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <p>Write printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">socket</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">sdata</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">¶</a> </div> <p>Write non-printable</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">socket</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">request</span><span class="p">.</span><span class="nx">end</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></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <p>Catch socket errors</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>Catch socket errors</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'error'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">request</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">¶</a> </div> <p>Remove data listener now that the 'handshake' is complete</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">request</span><span class="p">.</span><span class="nx">socket</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">handshake</span><span class="p">);</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>Write upgrade-head</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">¶</a> </div> <p>Remove data listener now that the 'handshake' is complete</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">request</span><span class="p">.</span><span class="nx">socket</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">handshake</span><span class="p">);</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">¶</a> </div> <p>Write upgrade-head</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
|
||||
<span class="nx">request</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">head</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">catch</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
||||
@ -389,9 +406,9 @@ So we split data to printable data and to non-printable
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">unwatch</span><span class="p">(</span><span class="nx">socket</span><span class="p">);</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">¶</a> </div> <p>Request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">onUpgrade</span><span class="p">(</span><span class="nx">reverse_proxy</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</a> </div> <p>Request</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">onUpgrade</span><span class="p">(</span><span class="nx">reverse_proxy</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">listeners</span> <span class="o">=</span> <span class="p">{};</span>
|
||||
</pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">¶</a> </div> <p>We're now connected to the server, so lets change server socket</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_r_data</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</a> </div> <p>Pass data to client</p> </td> <td class="code"> <div class="highlight"><pre> <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>
|
||||
</pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</a> </div> <p>We're now connected to the server, so lets change server socket</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_r_data</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">¶</a> </div> <p>Pass data to client</p> </td> <td class="code"> <div class="highlight"><pre> <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="k">try</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="nx">data</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
@ -402,19 +419,19 @@ So we split data to printable data and to non-printable
|
||||
<span class="p">}</span>
|
||||
<span class="p">});</span>
|
||||
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_data</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</a> </div> <p>Pass data from client to server</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_data</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</a> </div> <p>Pass data from client to server</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span> <span class="p">{</span>
|
||||
<span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">end</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></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">¶</a> </div> <p>Detach event listeners from reverse_proxy</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">detach</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="p">});</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">¶</a> </div> <p>Detach event listeners from reverse_proxy</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">detach</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'close'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_r_close</span><span class="p">);</span>
|
||||
<span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_r_data</span><span class="p">);</span>
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_data</span><span class="p">);</span>
|
||||
<span class="nx">socket</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'close'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_close</span><span class="p">);</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</a> </div> <p>Hook disconnections</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_r_close</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">¶</a> </div> <p>Hook disconnections</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverse_proxy</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="nx">listeners</span><span class="p">.</span><span class="nx">_r_close</span> <span class="o">=</span> <span class="kd">function</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="nx">detach</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
|
||||
@ -33,11 +33,15 @@
|
||||
|
||||
<h4>@silent {Boolean} Value indicating whether we should suppress logs</h4>
|
||||
|
||||
<h4>@hostnameOnly {Boolean} Value indicating if we should route based on <strong>hostname string only</strong></h4>
|
||||
|
||||
<p>Constructor function for the ProxyTable responsible for getting
|
||||
locations of proxy targets based on ServerRequest headers; specifically
|
||||
the HTTP host header.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">ProxyTable</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">ProxyTable</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">router</span><span class="p">,</span> <span class="nx">silent</span><span class="p">)</span> <span class="p">{</span>
|
||||
the HTTP host header.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">ProxyTable</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">ProxyTable</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">router</span><span class="p">,</span> <span class="nx">silent</span><span class="p">,</span> <span class="nx">hostnameOnly</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">events</span><span class="p">.</span><span class="nx">EventEmitter</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
|
||||
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">silent</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">silent</span> <span class="o">!==</span> <span class="s1">'undefined'</span> <span class="o">?</span> <span class="nx">silent</span> <span class="o">:</span> <span class="kc">true</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">hostnameOnly</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">hostnameOnly</span> <span class="o">!==</span> <span class="s1">'undefined'</span> <span class="o">?</span> <span class="nx">hostnameOnly</span> <span class="o">:</span> <span class="kc">false</span><span class="p">;</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">router</span> <span class="o">===</span> <span class="s1">'object'</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>If we are passed an object literal setup
|
||||
the routes with RegExps from the router </p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">setRoutes</span><span class="p">(</span><span class="nx">router</span><span class="p">);</span>
|
||||
@ -47,11 +51,11 @@ file path, parse that file and watch it for changes</p> </td>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">routeFile</span> <span class="o">=</span> <span class="nx">router</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">setRoutes</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">router</span><span class="p">)).</span><span class="nx">router</span><span class="p">);</span>
|
||||
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">watchFile</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">routeFile</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">c</span><span class="p">,</span><span class="nx">p</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">watchFile</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">routeFile</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span><span class="p">(</span><span class="nx">self</span><span class="p">.</span><span class="nx">routeFile</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="k">throw</span> <span class="nx">err</span><span class="p">;</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">setRoutes</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">data</span><span class="p">).</span><span class="nx">router</span><span class="p">);</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'routes'</span><span class="p">,</span> <span class="nx">self</span><span class="p">.</span><span class="nx">routes</span><span class="p">);</span>
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'routes'</span><span class="p">,</span> <span class="nx">self</span><span class="p">.</span><span class="nx">hostnameOnly</span> <span class="o">===</span> <span class="kc">false</span> <span class="o">?</span> <span class="nx">self</span><span class="p">.</span><span class="nx">routes</span> <span class="o">:</span> <span class="nx">self</span><span class="p">.</span><span class="nx">router</span><span class="p">);</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">}</span>
|
||||
@ -65,29 +69,35 @@ file path, parse that file and watch it for changes</p> </td>
|
||||
<p>Sets the host-based routes to be used by this instance. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">ProxyTable</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">setRoutes</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">router</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">router</span><span class="p">)</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'Cannot update ProxyTable routes without router.'</span><span class="p">);</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">router</span> <span class="o">=</span> <span class="nx">router</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">routes</span> <span class="o">=</span> <span class="p">[];</span>
|
||||
|
||||
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">router</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">route</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="s1">'i'</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">hostnameOnly</span> <span class="o">===</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nx">routes</span> <span class="o">=</span> <span class="p">[];</span>
|
||||
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">routes</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
|
||||
<span class="nx">route</span><span class="o">:</span> <span class="nx">route</span><span class="p">,</span>
|
||||
<span class="nx">target</span><span class="o">:</span> <span class="nx">router</span><span class="p">[</span><span class="nx">path</span><span class="p">]</span>
|
||||
<span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">router</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">route</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">path</span><span class="p">,</span> <span class="s1">'i'</span><span class="p">);</span>
|
||||
|
||||
<span class="nx">self</span><span class="p">.</span><span class="nx">routes</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
|
||||
<span class="nx">route</span><span class="o">:</span> <span class="nx">route</span><span class="p">,</span>
|
||||
<span class="nx">target</span><span class="o">:</span> <span class="nx">router</span><span class="p">[</span><span class="nx">path</span><span class="p">]</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <h3>function getProxyLocation (req)</h3>
|
||||
|
||||
<h4>@req {ServerRequest} The incoming server request to get proxy information about.</h4>
|
||||
|
||||
<p>Returns the proxy location based on the HTTP Headers in the ServerRequest <code>req</code>
|
||||
available to this instance.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">ProxyTable</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">getProxyLocation</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">req</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">host</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="k">this</span><span class="p">.</span><span class="nx">routes</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">match</span><span class="p">,</span> <span class="nx">route</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">routes</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">match</span> <span class="o">=</span> <span class="nx">target</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">route</span><span class="p">.</span><span class="nx">route</span><span class="p">))</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">location</span> <span class="o">=</span> <span class="nx">route</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">),</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">req</span> <span class="o">||</span> <span class="o">!</span><span class="nx">req</span><span class="p">.</span><span class="nx">headers</span> <span class="o">||</span> <span class="o">!</span><span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">host</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">host</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">hostnameOnly</span> <span class="o">==</span> <span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">router</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">target</span><span class="p">))</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">location</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">router</span><span class="p">[</span><span class="nx">target</span><span class="p">].</span><span class="nx">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">),</span>
|
||||
<span class="nx">host</span> <span class="o">=</span> <span class="nx">location</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
|
||||
<span class="nx">port</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">1</span> <span class="o">?</span> <span class="mi">80</span> <span class="o">:</span> <span class="nx">location</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
|
||||
|
||||
@ -99,6 +109,24 @@ available to this instance.</p> </td> <td class="code">
|
||||
<span class="p">};</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">else</span> <span class="p">{</span>
|
||||
<span class="nx">target</span> <span class="o">+=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="k">in</span> <span class="k">this</span><span class="p">.</span><span class="nx">routes</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">match</span><span class="p">,</span> <span class="nx">route</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">routes</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">match</span> <span class="o">=</span> <span class="nx">target</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">route</span><span class="p">.</span><span class="nx">route</span><span class="p">))</span> <span class="p">{</span>
|
||||
<span class="kd">var</span> <span class="nx">location</span> <span class="o">=</span> <span class="nx">route</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">),</span>
|
||||
<span class="nx">host</span> <span class="o">=</span> <span class="nx">location</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
|
||||
<span class="nx">port</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">1</span> <span class="o">?</span> <span class="mi">80</span> <span class="o">:</span> <span class="nx">location</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
|
||||
|
||||
<span class="nx">winston</span><span class="p">.</span><span class="nx">verbose</span><span class="p">(</span><span class="s1">'Proxy Table proxying request to: '</span> <span class="o">+</span> <span class="nx">host</span> <span class="o">+</span> <span class="s1">':'</span> <span class="o">+</span> <span class="nx">port</span><span class="p">);</span>
|
||||
|
||||
<span class="k">return</span> <span class="p">{</span>
|
||||
<span class="nx">port</span><span class="o">:</span> <span class="nx">port</span><span class="p">,</span>
|
||||
<span class="nx">host</span><span class="o">:</span> <span class="nx">host</span>
|
||||
<span class="p">};</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
|
||||
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>close function ()</h3>
|
||||
|
||||
@ -169,7 +169,7 @@ var HttpProxy = exports.HttpProxy = function (options) {
|
||||
|
||||
if (options.router) {
|
||||
var self = this;
|
||||
this.proxyTable = new ProxyTable(options.router, options.silent || false);
|
||||
this.proxyTable = new ProxyTable(options.router, options.silent, options.hostnameOnly);
|
||||
this.proxyTable.on('routes', function (routes) {
|
||||
self.emit('routes', routes);
|
||||
});
|
||||
@ -182,7 +182,7 @@ util.inherits(HttpProxy, events.EventEmitter);
|
||||
//
|
||||
// ### function buffer (obj)
|
||||
// #### @obj {Object} Object to pause events from
|
||||
// Pause `data` and `end` events on the given `obj`.
|
||||
// Buffer `data` and `end` events from the given `obj`.
|
||||
// Consumers of HttpProxy performing async tasks
|
||||
// __must__ utilize this utility, to re-emit data once
|
||||
// the async operation has completed, otherwise these
|
||||
@ -284,6 +284,12 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, buffer) {
|
||||
this._forwardRequest(req);
|
||||
}
|
||||
|
||||
//
|
||||
// #### function proxyError (err)
|
||||
// #### @err {Error} Error contacting the proxy target
|
||||
// Short-circuits `res` in the event of any error when
|
||||
// contacting the proxy target at `host` / `port`.
|
||||
//
|
||||
function proxyError(err) {
|
||||
errState = true;
|
||||
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
||||
@ -305,29 +311,33 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, buffer) {
|
||||
headers: req.headers
|
||||
}, function (response) {
|
||||
|
||||
// Process the reverseProxy response when it's received.
|
||||
// Process the `reverseProxy` `response` when it's received.
|
||||
if (response.headers.connection) {
|
||||
if (req.headers.connection) response.headers.connection = req.headers.connection;
|
||||
else response.headers.connection = 'close';
|
||||
}
|
||||
|
||||
// Set the response headers of the client response
|
||||
// Set the headers of the client response
|
||||
res.writeHead(response.statusCode, response.headers);
|
||||
|
||||
// Status code = 304
|
||||
// No 'data' event and no 'end'
|
||||
// `response.statusCode === 304`: No 'data' event and no 'end'
|
||||
if (response.statusCode === 304) {
|
||||
return res.end();
|
||||
}
|
||||
|
||||
// Add event handler for the proxied response in chunks
|
||||
// For each data `chunk` received from the `reverseProxy`
|
||||
// `response` write it to the outgoing `res`.
|
||||
response.on('data', function (chunk) {
|
||||
if (req.method !== 'HEAD') {
|
||||
res.write(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
// Add event listener for end of proxied response
|
||||
// When the `reverseProxy` `response` ends, end the
|
||||
// corresponding outgoing `res` unless we have entered
|
||||
// an error state. In which case, assume `res.end()` has
|
||||
// already been called and the 'error' event listener
|
||||
// removed.
|
||||
response.on('end', function () {
|
||||
if (!errState) {
|
||||
reverseProxy.removeListener('error', proxyError);
|
||||
@ -336,19 +346,33 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, buffer) {
|
||||
});
|
||||
});
|
||||
|
||||
// Add a listener for the connection timeout event
|
||||
// Handle 'error' events from the `reverseProxy`.
|
||||
reverseProxy.once('error', proxyError);
|
||||
|
||||
// Chunk the client request body as chunks from the proxied request come in
|
||||
// For each data `chunk` received from the incoming
|
||||
// `req` write it to the `reverseProxy` request.
|
||||
req.on('data', function (chunk) {
|
||||
if (!errState) {
|
||||
reverseProxy.write(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
// At the end of the client request, we are going to stop the proxied request
|
||||
//
|
||||
// When the incoming `req` ends, end the corresponding `reverseProxy`
|
||||
// request unless we have entered an error state.
|
||||
//
|
||||
req.on('end', function () {
|
||||
if (!errState) {
|
||||
//
|
||||
// __Remark__ *(indexzero | 3/10/2011)*: This is a short-term workaround for a suspect error from net.js when
|
||||
// `http.ClientRequest.end()` is called in reproducable, but uninvestigated scenarios
|
||||
//
|
||||
// net.js:313
|
||||
// throw new Error('Socket.end() called already; cannot write.');
|
||||
// ^
|
||||
// Error: Socket.end() called already; cannot write.
|
||||
// at Socket.write (net.js:313:13)
|
||||
//
|
||||
if (!errState && (!reverseProxy.socket || reverseProxy.socket._writeQueueLast() !== 42)) {
|
||||
reverseProxy.end();
|
||||
}
|
||||
});
|
||||
|
||||
@ -33,13 +33,16 @@ var util = require('util'),
|
||||
// ### function ProxyTable (router, silent)
|
||||
// #### @router {Object} Object containing the host based routes
|
||||
// #### @silent {Boolean} Value indicating whether we should suppress logs
|
||||
// #### @hostnameOnly {Boolean} Value indicating if we should route based on __hostname string only__
|
||||
// Constructor function for the ProxyTable responsible for getting
|
||||
// locations of proxy targets based on ServerRequest headers; specifically
|
||||
// the HTTP host header.
|
||||
//
|
||||
var ProxyTable = exports.ProxyTable = function (router, silent) {
|
||||
var ProxyTable = exports.ProxyTable = function (router, silent, hostnameOnly) {
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
this.silent = typeof silent !== 'undefined' ? silent : true;
|
||||
this.hostnameOnly = typeof hostnameOnly !== 'undefined' ? hostnameOnly : false;
|
||||
|
||||
if (typeof router === 'object') {
|
||||
//
|
||||
@ -57,11 +60,11 @@ var ProxyTable = exports.ProxyTable = function (router, silent) {
|
||||
this.routeFile = router;
|
||||
this.setRoutes(JSON.parse(fs.readFileSync(router)).router);
|
||||
|
||||
fs.watchFile(this.routeFile, function (c,p) {
|
||||
fs.watchFile(this.routeFile, function () {
|
||||
fs.readFile(self.routeFile, function (err, data) {
|
||||
if (err) throw err;
|
||||
self.setRoutes(JSON.parse(data).router);
|
||||
self.emit('routes', self.routes);
|
||||
self.emit('routes', self.hostnameOnly === false ? self.routes : self.router);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -81,18 +84,21 @@ util.inherits(ProxyTable, events.EventEmitter);
|
||||
ProxyTable.prototype.setRoutes = function (router) {
|
||||
if (!router) throw new Error('Cannot update ProxyTable routes without router.');
|
||||
|
||||
var self = this;
|
||||
this.router = router;
|
||||
this.routes = [];
|
||||
|
||||
Object.keys(router).forEach(function (path) {
|
||||
var route = new RegExp(path, 'i');
|
||||
if (this.hostnameOnly === false) {
|
||||
var self = this;
|
||||
this.routes = [];
|
||||
|
||||
self.routes.push({
|
||||
route: route,
|
||||
target: router[path]
|
||||
Object.keys(router).forEach(function (path) {
|
||||
var route = new RegExp(path, 'i');
|
||||
|
||||
self.routes.push({
|
||||
route: route,
|
||||
target: router[path]
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
@ -102,11 +108,14 @@ ProxyTable.prototype.setRoutes = function (router) {
|
||||
// available to this instance.
|
||||
//
|
||||
ProxyTable.prototype.getProxyLocation = function (req) {
|
||||
var target = req.headers.host.split(':')[0] + req.url;
|
||||
for (var i in this.routes) {
|
||||
var match, route = this.routes[i];
|
||||
if (match = target.match(route.route)) {
|
||||
var location = route.target.split(':'),
|
||||
if (!req || !req.headers || !req.headers.host) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var target = req.headers.host.split(':')[0];
|
||||
if (this.hostnameOnly == true) {
|
||||
if (this.router.hasOwnProperty(target)) {
|
||||
var location = this.router[target].split(':'),
|
||||
host = location[0],
|
||||
port = location.length === 1 ? 80 : location[1];
|
||||
|
||||
@ -118,6 +127,24 @@ ProxyTable.prototype.getProxyLocation = function (req) {
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
target += req.url;
|
||||
for (var i in this.routes) {
|
||||
var match, route = this.routes[i];
|
||||
if (match = target.match(route.route)) {
|
||||
var location = route.target.split(':'),
|
||||
host = location[0],
|
||||
port = location.length === 1 ? 80 : location[1];
|
||||
|
||||
winston.verbose('Proxy Table proxying request to: ' + host + ':' + port);
|
||||
|
||||
return {
|
||||
port: port,
|
||||
host: host
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -33,15 +33,33 @@ var defaultOptions = {
|
||||
}
|
||||
};
|
||||
|
||||
var hostnameOptions = {
|
||||
hostnameOnly: true,
|
||||
router: {
|
||||
"foo.com": "127.0.0.1:8091",
|
||||
"bar.com": "127.0.0.1:8092"
|
||||
},
|
||||
}
|
||||
|
||||
vows.describe('node-http-proxy/proxy-table').addBatch({
|
||||
"When using server created by httpProxy.createServer()": {
|
||||
"when passed a routing table": {
|
||||
topic: function () {
|
||||
this.server = runner.startProxyServerWithTable(8090, defaultOptions, this.callback);
|
||||
"and routing by RegExp": {
|
||||
topic: function () {
|
||||
this.server = runner.startProxyServerWithTable(8090, defaultOptions, this.callback);
|
||||
},
|
||||
"an incoming request to foo.com": assertProxiedWithTarget(runner, 'foo.com', 8090, 8091),
|
||||
"an incoming request to bar.com": assertProxiedWithTarget(runner, 'bar.com', 8090, 8092),
|
||||
"an incoming request to unknown.com": assertProxiedWithNoTarget(runner, 8090, 404)
|
||||
},
|
||||
"an incoming request to foo.com": assertProxiedWithTarget(runner, 'foo.com', 8090, 8091),
|
||||
"an incoming request to bar.com": assertProxiedWithTarget(runner, 'bar.com', 8090, 8092),
|
||||
"an incoming request to unknown.com": assertProxiedWithNoTarget(runner, 8090, 404)
|
||||
"and routing by Hostname": {
|
||||
topic: function () {
|
||||
this.server = runner.startProxyServerWithTable(8093, hostnameOptions, this.callback);
|
||||
},
|
||||
"an incoming request to foo.com": assertProxiedWithTarget(runner, 'foo.com', 8093, 8094),
|
||||
"an incoming request to bar.com": assertProxiedWithTarget(runner, 'bar.com', 8093, 8095),
|
||||
"an incoming request to unknown.com": assertProxiedWithNoTarget(runner, 8093, 404)
|
||||
}
|
||||
},
|
||||
"when passed a routing file": {
|
||||
topic: function () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user