node-http-proxy/docs/node-http-proxy.html
2011-05-18 21:06:21 -04:00

514 lines
99 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 &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="balancing-proxy.html"> balancing-proxy.html </a> <a class="source" href="node-http-proxy.html"> node-http-proxy.html </a> <a class="source" href="proxy-table.html"> proxy-table.html </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> 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">&#182;</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"> &quot;Software&quot;), to deal in the Software without restriction, including</span>
<span class="cm"> without limitation the rights to use, copy, modify, merge, publish,</span>
<span class="cm"> distribute, sublicense, and/or sell copies of the Software, and to</span>
<span class="cm"> permit persons to whom the Software is furnished to do so, subject to</span>
<span class="cm"> the following conditions:</span>
<span class="cm"> The above copyright notice and this permission notice shall be</span>
<span class="cm"> included in all copies or substantial portions of the Software.</span>
<span class="cm"> THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,</span>
<span class="cm"> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF</span>
<span class="cm"> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND</span>
<span class="cm"> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE</span>
<span class="cm"> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION</span>
<span class="cm"> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION</span>
<span class="cm"> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</span>
<span class="cm">*/</span>
<span class="kd">var</span> <span class="nx">util</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;util&#39;</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">&#39;http&#39;</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">&#39;https&#39;</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">&#39;events&#39;</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">&#39;./proxy-table&#39;</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">&#182;</a> </div> <h3>Version 0.5.3 // 5/17/2011</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">3</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">&#182;</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">&#182;</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">&#39;object&#39;</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">&#39;ca&#39;</span><span class="p">,</span> <span class="s1">&#39;cert&#39;</span><span class="p">,</span> <span class="s1">&#39;key&#39;</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">&#182;</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">&#182;</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">&#182;</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">&#39;function&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">(),</span>
<span class="nx">options</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">port</span><span class="p">,</span> <span class="nx">host</span><span class="p">,</span> <span class="nx">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">&gt;=</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">&amp;&amp;</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">&#39;Cannot create server with no router and no callback&#39;</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">&#182;</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">&amp;&amp;</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">&#182;</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">&#182;</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">&#182;</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">&#39;Cannot proxy without port, host, or router.&#39;</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">&#39;close&#39;</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">&#39;routes&#39;</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">&#39;routes&#39;</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">&#182;</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">&#39;upgrade&#39;</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">&#182;</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">&#182;</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">&#182;</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="nx">options</span><span class="p">.</span><span class="nx">target</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">target</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">target</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">changeOrigin</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">changeOrigin</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="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">&#39;routes&#39;</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">&#39;routes&#39;</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">&#182;</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">&#182;</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 &lt; 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">&#39;data&#39;</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">&#39;data&#39;</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">&#39;end&#39;</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">&#39;end&#39;</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">&#39;data&#39;</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">&#39;end&#39;</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">&lt;</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">&#182;</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">&#182;</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">&#182;</a> </div> <p>Create an empty options hash if none is passed.
If default options have been passed to the constructor
of this instance, use them by default.</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>
<span class="nx">options</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="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">target</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="o">=</span> <span class="nx">options</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">target</span><span class="p">.</span><span class="nx">port</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">&#182;</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">&amp;&amp;</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">&#182;</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">&#182;</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">&#182;</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">&#39;x-forwarded-for&#39;</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">&#182;</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">&#39;start&#39;</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">&#182;</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">&#39;forward&#39;</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">&#182;</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">&#39;Content-Type&#39;</span><span class="o">:</span> <span class="s1">&#39;text/plain&#39;</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">&#39;HEAD&#39;</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">&#39;An error has occurred: &#39;</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">target</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">&#182;</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">&#39;connection&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;close&#39;</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">target</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">&#182;</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">&#182;</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">&#39;close&#39;</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">&#182;</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">&#182;</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">&#182;</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">&#39;data&#39;</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">&#39;HEAD&#39;</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">&#182;</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">&#39;end&#39;</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">&#39;error&#39;</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">&#182;</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">&#39;end&#39;</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">&#182;</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">&#39;error&#39;</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">&#182;</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">&#39;data&#39;</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">&#182;</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">&#39;end&#39;</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">&#182;</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">&amp;&amp;</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">&#182;</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">&#182;</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">&#39;connection&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;close&#39;</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">&#182;</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">&#182;</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">&#182;</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">&#39;error&#39;</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">&#182;</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">&#39;data&#39;</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">&#182;</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">&#39;end&#39;</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">&#39;\r\n&#39;</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">&#182;</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">&#39;GET&#39;</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">&#39;websocket&#39;</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">&#182;</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">&#182;</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="k">if</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="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="k">if</span> <span class="p">(</span><span class="nx">socket</span><span class="p">.</span><span class="nx">pair</span><span class="p">.</span><span class="nx">cleartext</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="p">{</span>
<span class="nx">socket</span><span class="p">.</span><span class="nx">pair</span><span class="p">.</span><span class="nx">cleartext</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="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">&#39;utf8&#39;</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">&#182;</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">&#39;data&#39;</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">&#182;</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">&#39;data&#39;</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">&#182;</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">&#182;</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">&#39;close&#39;</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">&#39;data&#39;</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">&#39;data&#39;</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">&#39;close&#39;</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">&#182;</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">&#39;end&#39;</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">&#39;end&#39;</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">&#182;</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">&#182;</a> </div> <p>Remote host address</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">protocolName</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="k">this</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">https</span> <span class="o">?</span> <span class="s1">&#39;https&#39;</span> <span class="o">:</span> <span class="s1">&#39;http&#39;</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">target</span><span class="p">.</span><span class="nx">https</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">&#39;&#39;</span> <span class="o">:</span> <span class="s1">&#39;:&#39;</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">&#182;</a> </div> <p>Change headers</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">changeOrigin</span><span class="p">)</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">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="nx">protocolName</span> <span class="o">+</span> <span class="s1">&#39;://&#39;</span> <span class="o">+</span> <span class="nx">remoteHost</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">method</span><span class="o">:</span> <span class="s1">&#39;GET&#39;</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">&#182;</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">&#182;</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">&#182;</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">&#39;upgrade&#39;</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">&#39;upgrade&#39;</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">&#182;</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">&#182;</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">&#39;undefined&#39;</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">&#39;data&#39;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#182;</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">&#39;error&#39;</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">&#182;</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">&#39;data&#39;</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">&#182;</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">&#182;</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">&amp;&amp;</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>