mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
500 lines
96 KiB
HTML
500 lines
96 KiB
HTML
<!DOCTYPE html> <html> <head> <title>node-http-proxy.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="node-http-proxy.html"> node-http-proxy.js </a> <a class="source" href="proxy-table.html"> proxy-table.js </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> node-http-proxy.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="cm">/*</span>
|
|
<span class="cm"> node-http-proxy.js: http proxy for node.js</span>
|
|
|
|
<span class="cm"> Copyright (c) 2010 Charlie Robbins, Mikeal Rogers, Marak Squires, Fedor Indutny </span>
|
|
|
|
<span class="cm"> Permission is hereby granted, free of charge, to any person obtaining</span>
|
|
<span class="cm"> a copy of this software and associated documentation files (the</span>
|
|
<span class="cm"> "Software"), to deal in the Software without restriction, including</span>
|
|
<span class="cm"> without limitation the rights to use, copy, modify, merge, publish,</span>
|
|
<span class="cm"> distribute, sublicense, and/or sell copies of the Software, and to</span>
|
|
<span class="cm"> permit persons to whom the Software is furnished to do so, subject to</span>
|
|
<span class="cm"> the following conditions:</span>
|
|
|
|
<span class="cm"> The above copyright notice and this permission notice shall be</span>
|
|
<span class="cm"> included in all copies or substantial portions of the Software.</span>
|
|
|
|
<span class="cm"> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,</span>
|
|
<span class="cm"> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF</span>
|
|
<span class="cm"> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND</span>
|
|
<span class="cm"> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE</span>
|
|
<span class="cm"> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION</span>
|
|
<span class="cm"> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION</span>
|
|
<span class="cm"> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>
|
|
|
|
<span class="cm">*/</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">util</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'util'</span><span class="p">),</span>
|
|
<span class="nx">http</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'http'</span><span class="p">),</span>
|
|
<span class="nx">https</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'https'</span><span class="p">),</span>
|
|
<span class="nx">events</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'events'</span><span class="p">),</span>
|
|
<span class="nx">ProxyTable</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./proxy-table'</span><span class="p">).</span><span class="nx">ProxyTable</span><span class="p">,</span>
|
|
<span class="nx">maxSockets</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>Version 0.5.0</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">version</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">0</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> <h3>function _getAgent (host, port, secure)</h3>
|
|
|
|
<h4>@host {string} Host of the agent to get</h4>
|
|
|
|
<h4>@port {number} Port of the agent to get</h4>
|
|
|
|
<h4>@secure {boolean} Value indicating whether or not to use HTTPS</h4>
|
|
|
|
<p>Retreives an agent from the <code>http</code> or <code>https</code> module
|
|
and sets the <code>maxSockets</code> property appropriately.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">function</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">secure</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">agent</span> <span class="o">=</span> <span class="o">!</span><span class="nx">secure</span> <span class="o">?</span> <span class="nx">http</span><span class="p">.</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="o">:</span> <span class="nx">https</span><span class="p">.</span><span class="nx">getAgent</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="p">.</span><span class="nx">maxSockets</span> <span class="o">=</span> <span class="nx">maxSockets</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">agent</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <h3>function _getProtocol (secure, outgoing)</h3>
|
|
|
|
<h4>@secure {Object|boolean} Settings for <code>https</code></h4>
|
|
|
|
<h4>@outgoing {Object} Outgoing request options</h4>
|
|
|
|
<p>Returns the appropriate protocol based on the settings in
|
|
<code>secure</code>. If the protocol is <code>https</code> this function will update
|
|
the options in <code>outgoing</code> as appropriate by adding <code>ca</code>, <code>key</code>,
|
|
and <code>cert</code> if they exist in <code>secure</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="kd">function</span> <span class="nx">_getProtocol</span> <span class="p">(</span><span class="nx">secure</span><span class="p">,</span> <span class="nx">outgoing</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">protocol</span> <span class="o">=</span> <span class="nx">secure</span> <span class="o">?</span> <span class="nx">https</span> <span class="o">:</span> <span class="nx">http</span><span class="p">;</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">secure</span> <span class="o">===</span> <span class="s1">'object'</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">outgoing</span> <span class="o">=</span> <span class="nx">outgoing</span> <span class="o">||</span> <span class="p">{};</span>
|
|
<span class="p">[</span><span class="s1">'ca'</span><span class="p">,</span> <span class="s1">'cert'</span><span class="p">,</span> <span class="s1">'key'</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">prop</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">secure</span><span class="p">[</span><span class="nx">prop</span><span class="p">])</span> <span class="p">{</span>
|
|
<span class="nx">outgoing</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">=</span> <span class="nx">secure</span><span class="p">[</span><span class="nx">prop</span><span class="p">];</span>
|
|
<span class="p">}</span>
|
|
<span class="p">})</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="nx">protocol</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <h3>function getMaxSockets ()</h3>
|
|
|
|
<p>Returns the maximum number of sockets
|
|
allowed on <strong>every</strong> outgoing request
|
|
made by <strong>all</strong> instances of <code>HttpProxy</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">getMaxSockets</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="nx">maxSockets</span><span class="p">;</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h3>function setMaxSockets ()</h3>
|
|
|
|
<p>Sets the maximum number of sockets
|
|
allowed on <strong>every</strong> outgoing request
|
|
made by <strong>all</strong> instances of <code>HttpProxy</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">setMaxSockets</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">maxSockets</span> <span class="o">=</span> <span class="nx">value</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 createServer ([port, host, options, handler])</h3>
|
|
|
|
<h4>@port {number} <strong>Optional</strong> Port to use on the proxy target host.</h4>
|
|
|
|
<h4>@host {string} <strong>Optional</strong> Host of the proxy target.</h4>
|
|
|
|
<h4>@options {Object} <strong>Optional</strong> Options for the HttpProxy instance used</h4>
|
|
|
|
<h4>@handler {function} <strong>Optional</strong> Request handler for the server</h4>
|
|
|
|
<p>Returns a server that manages an instance of HttpProxy. Flexible arguments allow for:</p>
|
|
|
|
<ul>
|
|
<li><code>httpProxy.createServer(9000, 'localhost')</code></li>
|
|
<li>`httpProxy.createServer(9000, 'localhost', options)</li>
|
|
<li><code>httpPRoxy.createServer(function (req, res, proxy) { ... })</code></li>
|
|
</ul> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</span><span class="p">.</span><span class="nx">createServer</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">slice</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">arguments</span><span class="p">),</span>
|
|
<span class="nx">callback</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="s1">'function'</span> <span class="o">&&</span> <span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">(),</span>
|
|
<span class="nx">options</span> <span class="o">=</span> <span class="p">{},</span>
|
|
<span class="nx">port</span><span class="p">,</span> <span class="nx">host</span><span class="p">,</span> <span class="nx">forward</span><span class="p">,</span> <span class="nx">silent</span><span class="p">,</span> <span class="nx">proxy</span><span class="p">,</span> <span class="nx">server</span><span class="p">;</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">port</span> <span class="o">=</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
|
|
<span class="nx">host</span> <span class="o">=</span> <span class="nx">args</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
|
|
<span class="nx">options</span> <span class="o">=</span> <span class="nx">args</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">||</span> <span class="p">{};</span>
|
|
<span class="p">}</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">options</span> <span class="o">=</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">||</span> <span class="p">{};</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">router</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">callback</span><span class="p">)</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 create server with no router and no callback'</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="nx">proxy</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HttpProxy</span><span class="p">(</span><span class="nx">options</span><span class="p">);</span>
|
|
|
|
<span class="nx">handler</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="nx">res</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">callback</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> <p>If we were passed a callback to process the request
|
|
or response in some way, then call it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">callback</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">proxy</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">port</span> <span class="o">&&</span> <span class="nx">host</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>If we have a target host and port for the request
|
|
then proxy to the specified location.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">proxy</span><span class="p">.</span><span class="nx">proxyRequest</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</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="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">proxy</span><span class="p">.</span><span class="nx">proxyTable</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>If the proxy is configured with a ProxyTable
|
|
instance then use that before failing.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">proxy</span><span class="p">.</span><span class="nx">proxyRequest</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">else</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Otherwise this server is improperly configured.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">'Cannot proxy without port, host, or router.'</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">};</span>
|
|
|
|
<span class="nx">server</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">https</span>
|
|
<span class="o">?</span> <span class="nx">https</span><span class="p">.</span><span class="nx">createServer</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">https</span><span class="p">,</span> <span class="nx">handler</span><span class="p">)</span>
|
|
<span class="o">:</span> <span class="nx">http</span><span class="p">.</span><span class="nx">createServer</span><span class="p">(</span><span class="nx">handler</span><span class="p">);</span>
|
|
|
|
<span class="nx">server</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">'close'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">proxy</span><span class="p">.</span><span class="nx">close</span><span class="p">();</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="nx">proxy</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">server</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>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>WebSocket support: if callback is empty tunnel
|
|
websocket request automatically</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">server</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">req</span><span class="p">,</span> <span class="nx">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-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Tunnel websocket requests too</p> </td> <td class="code"> <div class="highlight"><pre>
|
|
<span class="nx">proxy</span><span class="p">.</span><span class="nx">proxyWebSocketRequest</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">socket</span><span class="p">,</span> <span class="nx">head</span><span class="p">,</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>
|
|
</pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Set the proxy on the server so it is available
|
|
to the consumer of the server</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">server</span><span class="p">.</span><span class="nx">proxy</span> <span class="o">=</span> <span class="nx">proxy</span><span class="p">;</span>
|
|
|
|
<span class="k">return</span> <span class="nx">server</span><span class="p">;</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <h3>function HttpProxy (options)</h3>
|
|
|
|
<h4>@options {Object} Options for this instance.</h4>
|
|
|
|
<p>Constructor function for new instances of HttpProxy responsible
|
|
for managing the life-cycle of streaming reverse proxyied HTTP requests.</p>
|
|
|
|
<p>Example options:</p>
|
|
|
|
<pre><code> {
|
|
router: {
|
|
'foo.com': 'localhost:8080',
|
|
'bar.com': 'localhost:8081'
|
|
},
|
|
forward: {
|
|
host: 'localhost',
|
|
port: 9001
|
|
}
|
|
}
|
|
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="kd">var</span> <span class="nx">HttpProxy</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">HttpProxy</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">options</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="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
|
|
<span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</span> <span class="p">{};</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">forward</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">forward</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">https</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">https</span><span class="p">;</span>
|
|
|
|
<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="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>
|
|
<span class="p">}</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Inherit from events.EventEmitter</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">util</span><span class="p">.</span><span class="nx">inherits</span><span class="p">(</span><span class="nx">HttpProxy</span><span class="p">,</span> <span class="nx">events</span><span class="p">.</span><span class="nx">EventEmitter</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <h3>function buffer (obj)</h3>
|
|
|
|
<h4>@obj {Object} Object to pause events from</h4>
|
|
|
|
<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
|
|
<strong>events will be lost.</strong></p>
|
|
|
|
<pre><code> var buffer = httpProxy.buffer(req);
|
|
fs.readFile(path, function(){
|
|
httpProxy.proxyRequest(req, res, host, port, buffer);
|
|
});
|
|
</code></pre>
|
|
|
|
<p><strong>Attribution:</strong> This approach is based heavily on
|
|
<a href="https://github.com/senchalabs/connect/blob/master/lib/utils.js#L157">Connect</a>.
|
|
However, this is not a big leap from the implementation in node-http-proxy < 0.4.0.
|
|
This simply chooses to manage the scope of the events on a new Object literal as opposed to
|
|
<a href="https://github.com/nodejitsu/node-http-proxy/blob/v0.3.1/lib/node-http-proxy.js#L154">on the HttpProxy instance</a>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">HttpProxy</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">buffer</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">obj</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">onData</span><span class="p">,</span> <span class="nx">onEnd</span><span class="p">,</span> <span class="nx">events</span> <span class="o">=</span> <span class="p">[];</span>
|
|
|
|
<span class="nx">obj</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">onData</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="nx">encoding</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">events</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">'data'</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">encoding</span><span class="p">]);</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="nx">obj</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">onEnd</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="nx">encoding</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">events</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">'end'</span><span class="p">,</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">encoding</span><span class="p">]);</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="k">return</span> <span class="p">{</span>
|
|
<span class="nx">end</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">obj</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">onData</span><span class="p">);</span>
|
|
<span class="nx">obj</span><span class="p">.</span><span class="nx">removeListener</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="nx">onEnd</span><span class="p">);</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">resume</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">end</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="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">events</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">len</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">obj</span><span class="p">.</span><span class="nx">emit</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">events</span><span class="p">[</span><span class="nx">i</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-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <h3>function close ()</h3>
|
|
|
|
<p>Frees the resources associated with this instance,
|
|
if they exist. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">HttpProxy</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">close</span> <span class="o">=</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="k">this</span><span class="p">.</span><span class="nx">proxyTable</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">close</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> <h3>function proxyRequest (req, res, [port, host, paused])</h3>
|
|
|
|
<h4>@req {ServerRequest} Incoming HTTP Request to proxy.</h4>
|
|
|
|
<h4>@res {ServerResponse} Outgoing HTTP Request to write proxied data to.</h4>
|
|
|
|
<h4>@options {Object} Options for the outgoing proxy request.</h4>
|
|
|
|
<pre><code>options.port {number} Port to use on the proxy target host.
|
|
options.host {string} Host of the proxy target.
|
|
options.buffer {Object} Result from `httpProxy.buffer(req)`
|
|
options.https {Object|boolean} Settings for https.
|
|
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nx">HttpProxy</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">proxyRequest</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="nx">res</span><span class="p">,</span> <span class="nx">options</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">errState</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">location</span><span class="p">,</span> <span class="nx">outgoing</span><span class="p">,</span> <span class="nx">protocol</span><span class="p">,</span> <span class="nx">reverseProxy</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>Create an empty options hash if none is passed.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">=</span> <span class="nx">options</span> <span class="o">||</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>Check the proxy table for this instance to see if we need
|
|
to get the proxy location for the request supplied. We will
|
|
always ignore the proxyTable if an explicit <code>port</code> and <code>host</code>
|
|
arguments are supplied to <code>proxyRequest</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</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="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">host</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">location</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">proxyTable</span><span class="p">.</span><span class="nx">getProxyLocation</span><span class="p">(</span><span class="nx">req</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>If no location is returned from the ProxyTable instance
|
|
then respond with <code>404</code> since we do not have a valid proxy target.</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">location</span><span class="p">)</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">404</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>When using the ProxyTable in conjunction with an HttpProxy instance
|
|
only the following arguments are valid:</p>
|
|
|
|
<ul>
|
|
<li><code>proxy.proxyRequest(req, res, { host: 'localhost' })</code>: This will be skipped</li>
|
|
<li><code>proxy.proxyRequest(req, res, { buffer: buffer })</code>: Buffer will get updated appropriately</li>
|
|
<li><code>proxy.proxyRequest(req, res)</code>: Options will be assigned appropriately. </li>
|
|
</ul> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</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">port</span><span class="p">;</span>
|
|
<span class="nx">options</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="nx">host</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 <code>x-forwarded-for</code> header to availible client IP to apps behind proxy</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">[</span><span class="s1">'x-forwarded-for'</span><span class="p">]</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">connection</span><span class="p">.</span><span class="nx">remoteAddress</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>Emit the <code>start</code> event indicating that we have begun the proxy operation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'start'</span><span class="p">,</span> <span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">options</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>If forwarding is enabled for this instance, foward proxy the
|
|
specified request to the address provided in <code>this.forward</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">forward</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'forward'</span><span class="p">,</span> <span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">forward</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>
|
|
</pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</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>
|
|
|
|
<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="s1">'An error has occurred: '</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">err</span><span class="p">));</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="nx">outgoing</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">host</span><span class="o">:</span> <span class="nx">options</span><span class="p">.</span><span class="nx">host</span><span class="p">,</span>
|
|
<span class="nx">port</span><span class="o">:</span> <span class="nx">options</span><span class="p">.</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">options</span><span class="p">.</span><span class="nx">host</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">port</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">https</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">https</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>
|
|
</pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Force the <code>connection</code> header to be 'close' until
|
|
node.js core re-implements 'keep-alive'.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">outgoing</span><span class="p">.</span><span class="nx">headers</span><span class="p">[</span><span class="s1">'connection'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'close'</span><span class="p">;</span>
|
|
|
|
<span class="nx">protocol</span> <span class="o">=</span> <span class="nx">_getProtocol</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">https</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">https</span><span class="p">,</span> <span class="nx">outgoing</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>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">protocol</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="nx">outgoing</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-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</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-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</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-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</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-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</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-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</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>
|
|
</pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</a> </div> <p>Emit the <code>end</code> event now that we have completed proxying</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">self</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s1">'end'</span><span class="p">,</span> <span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</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>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-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</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-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</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>
|
|
<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">end</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>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">options</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">options</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-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <h3>@private function _forwardRequest (req)</h3>
|
|
|
|
<h4>@req {ServerRequest} Incoming HTTP Request to proxy.</h4>
|
|
|
|
<p>Forwards the specified <code>req</code> to the location specified
|
|
by <code>this.forward</code> ignoring errors and the subsequent response.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">HttpProxy</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">_forwardRequest</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">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span> <span class="nx">port</span><span class="p">,</span> <span class="nx">host</span><span class="p">,</span> <span class="nx">outgoing</span><span class="p">,</span> <span class="nx">protocol</span><span class="p">,</span> <span class="nx">forwardProxy</span><span class="p">;</span>
|
|
|
|
<span class="nx">port</span> <span class="o">=</span> <span class="k">this</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">forward</span><span class="p">.</span><span class="nx">host</span><span class="p">;</span>
|
|
|
|
<span class="nx">outgoing</span> <span class="o">=</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="k">this</span><span class="p">.</span><span class="nx">forward</span><span class="p">.</span><span class="nx">https</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>
|
|
</pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>Force the <code>connection</code> header to be 'close' until
|
|
node.js core re-implements 'keep-alive'.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">outgoing</span><span class="p">.</span><span class="nx">headers</span><span class="p">[</span><span class="s1">'connection'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'close'</span><span class="p">;</span>
|
|
|
|
<span class="nx">protocol</span> <span class="o">=</span> <span class="nx">_getProtocol</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">forward</span><span class="p">.</span><span class="nx">https</span><span class="p">,</span> <span class="nx">outgoing</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>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">protocol</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="nx">outgoing</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-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</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-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</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">once</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-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</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-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</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">req</span><span class="p">,</span> <span class="nx">socket</span><span class="p">,</span> <span class="nx">head</span><span class="p">,</span> <span class="nx">options</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">outgoing</span><span class="p">,</span> <span class="nx">errState</span> <span class="o">=</span> <span class="kc">false</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-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</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">req</span><span class="p">.</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-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</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-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</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">keepAlive</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>
|
|
<span class="nx">socket</span><span class="p">.</span><span class="nx">setNoDelay</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">keepAlive</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">socket</span><span class="p">.</span><span class="nx">setKeepAlive</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<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>
|
|
|
|
<span class="kd">function</span> <span class="nx">onUpgrade</span><span class="p">(</span><span class="nx">out</span><span class="p">,</span> <span class="nx">reverseProxy</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">out</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="nx">socket</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
|
<span class="k">return</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-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</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">reverseProxy</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-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</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">out</span><span class="p">.</span><span class="nx">incoming</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">out</span><span class="p">.</span><span class="nx">incoming</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>
|
|
<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">out</span><span class="p">.</span><span class="nx">incoming</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">reverseProxy</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>
|
|
|
|
<span class="nx">out</span><span class="p">.</span><span class="nx">incoming</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-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</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">reverseProxy</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">reverseProxy</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-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>Detach event listeners from reverseProxy</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">reverseProxy</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">reverseProxy</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">out</span><span class="p">.</span><span class="nx">incoming</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">out</span><span class="p">.</span><span class="nx">incoming</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-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>Hook disconnections</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">reverseProxy</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">out</span><span class="p">.</span><span class="nx">incoming</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>
|
|
|
|
<span class="nx">socket</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">_close</span> <span class="o">=</span> <span class="kd">function</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="nx">detach</span><span class="p">();</span>
|
|
<span class="p">});</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>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-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <p>Remote host address</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">agent</span> <span class="o">=</span> <span class="nx">_getAgent</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">host</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">port</span><span class="p">),</span>
|
|
<span class="nx">remoteHost</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">host</span> <span class="o">+</span> <span class="p">(</span><span class="nx">options</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">options</span><span class="p">.</span><span class="nx">port</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>Change headers</p> </td> <td class="code"> <div class="highlight"><pre> <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="o">=</span> <span class="nx">remoteHost</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">origin</span> <span class="o">=</span> <span class="s1">'http://'</span> <span class="o">+</span> <span class="nx">options</span><span class="p">.</span><span class="nx">host</span><span class="p">;</span>
|
|
|
|
<span class="nx">outgoing</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">host</span><span class="o">:</span> <span class="nx">options</span><span class="p">.</span><span class="nx">host</span><span class="p">,</span>
|
|
<span class="nx">port</span><span class="o">:</span> <span class="nx">options</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="s1">'GET'</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="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>Make the outgoing WebSocket request</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">agent</span><span class="p">.</span><span class="nx">appendMessage</span><span class="p">(</span><span class="nx">outgoing</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>Here we set the incoming <code>req</code>, <code>socket</code> and <code>head</code> data to the outgoing
|
|
request so that we can reuse this data later on in the closure scope
|
|
available to the <code>upgrade</code> event. This bookkeeping is not tracked anywhere
|
|
in nodejs core and is <strong>very</strong> specific to proxying WebSockets.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">request</span><span class="p">.</span><span class="nx">agent</span> <span class="o">=</span> <span class="nx">agent</span><span class="p">;</span>
|
|
<span class="nx">request</span><span class="p">.</span><span class="nx">incoming</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">request</span><span class="o">:</span> <span class="nx">req</span><span class="p">,</span>
|
|
<span class="nx">socket</span><span class="o">:</span> <span class="nx">socket</span><span class="p">,</span>
|
|
<span class="nx">head</span><span class="o">:</span> <span class="nx">head</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>If the agent for this particular <code>host</code> and <code>port</code> combination
|
|
is not already listening for the <code>upgrade</code> event, then do so once.
|
|
This will force us not to disconnect. </p>
|
|
|
|
<p>In addition, it's important to note the closure scope here. Since
|
|
there is no mapping of the </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">agent</span><span class="p">.</span><span class="nx">_events</span> <span class="o">||</span> <span class="nx">agent</span><span class="p">.</span><span class="nx">_events</span><span class="p">[</span><span class="s1">'upgrade'</span><span class="p">].</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">agent</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">out</span><span class="p">,</span> <span class="nx">remoteSocket</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-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</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">remoteSocket</span><span class="p">,</span> <span class="kc">true</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>Emit event</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">onUpgrade</span><span class="p">(</span><span class="nx">remoteSocket</span><span class="p">.</span><span class="nx">_httpMessage</span><span class="p">,</span> <span class="nx">remoteSocket</span><span class="p">);</span>
|
|
<span class="p">});</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">request</span><span class="p">.</span><span class="nx">socket</span> <span class="o">!==</span> <span class="s1">'undefined'</span><span class="p">)</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="kd">function</span> <span class="nx">handshake</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>Handshaking</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</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-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">¶</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-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">¶</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-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">¶</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">remoteHost</span><span class="p">,</span> <span class="nx">options</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">remoteHost</span><span class="p">,</span> <span class="nx">options</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-68"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-68">¶</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-69"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-69">¶</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-70"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-70">¶</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-71"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-71">¶</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>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-72">¶</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">ex</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-73"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-73">¶</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">options</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">options</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> </tbody> </table> </div> </body> </html> |