</pre></div></td></tr><trid="section-24"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-24">¶</a></div><p>Add <code>x-forwarded-for</code> header to availible client IP to apps behind proxy</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">[</span><spanclass="s1">'x-forwarded-for'</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">connection</span><spanclass="p">.</span><spanclass="nx">remoteAddress</span><spanclass="p">;</span>
</pre></div></td></tr><trid="section-24"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-24">¶</a></div><p>Add common proxy headers to the request so that they can
be availible to the proxy target server:</p>
<ul>
<li><code>x-forwarded-for</code>: IP Address of the original request</li>
<li><code>x-forwarded-proto</code>: Protocol of the original request</li>
<li><code>x-forwarded-port</code>: Port of the original request. </li>
</pre></div></td></tr><trid="section-25"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-25">¶</a></div><p>Emit the <code>start</code> event indicating that we have begun the proxy operation.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">this</span><spanclass="p">.</span><spanclass="nx">emit</span><spanclass="p">(</span><spanclass="s1">'start'</span><spanclass="p">,</span><spanclass="nx">req</span><spanclass="p">,</span><spanclass="nx">res</span><spanclass="p">,</span><spanclass="nx">options</span><spanclass="p">);</span>
</pre></div></td></tr><trid="section-26"><tdclass="docs"><divclass="pilwrap"><aclass="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><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="k">this</span><spanclass="p">.</span><spanclass="nx">forward</span><spanclass="p">)</span><spanclass="p">{</span>
...
...
@@ -293,11 +302,21 @@ specified request to the address provided in <code>this.forward</code></p>
<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><tdclass="code"><divclass="highlight"><pre><spanclass="kd">function</span><spanclass="nx">proxyError</span><spanclass="p">(</span><spanclass="nx">err</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-28"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-28">¶</a></div><p>Emit an <code>error</code> event, allowing the application to use custom
error handling. The error handler should end the response.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">self</span><spanclass="p">.</span><spanclass="nx">emit</span><spanclass="p">(</span><spanclass="s1">'proxyError'</span><spanclass="p">,</span><spanclass="nx">err</span><spanclass="p">,</span><spanclass="nx">req</span><spanclass="p">,</span><spanclass="nx">res</span><spanclass="p">))</span><spanclass="p">{</span>
<spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">method</span><spanclass="o">!==</span><spanclass="s1">'HEAD'</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-29"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-29">¶</a></div><p>This NODE_ENV=production behavior is mimics Express and
<spanclass="nx">res</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="p">(</span><spanclass="s1">'Internal Server Error'</span><spanclass="p">);</span>
<spanclass="p">}</span>
<spanclass="k">else</span><spanclass="p">{</span>
<spanclass="nx">res</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="p">(</span><spanclass="s1">'An error has occurred: '</span><spanclass="o">+</span><spanclass="nx">JSON</span><spanclass="p">.</span><spanclass="nx">stringify</span><spanclass="p">(</span><spanclass="nx">err</span><spanclass="p">));</span>
</pre></div></td></tr><trid="section-28"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-28">¶</a></div><p>Force the <code>connection</code> header to be 'close' until
</pre></div></td></tr><trid="section-30"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-30">¶</a></div><p>Force the <code>connection</code> header to be 'close' until
</pre></div></td></tr><trid="section-29"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-29">¶</a></div><p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="o">=</span><spanclass="nx">protocol</span><spanclass="p">.</span><spanclass="nx">request</span><spanclass="p">(</span><spanclass="nx">outgoing</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-30"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-30">¶</a></div><p>Process the <code>reverseProxy</code><code>response</code> when it's received.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">.</span><spanclass="nx">connection</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-31"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-31">¶</a></div><p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="o">=</span><spanclass="nx">protocol</span><spanclass="p">.</span><spanclass="nx">request</span><spanclass="p">(</span><spanclass="nx">outgoing</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-32"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-32">¶</a></div><p>Process the <code>reverseProxy</code><code>response</code> when it's received.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">.</span><spanclass="nx">connection</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-31"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-31">¶</a></div><p>Set the headers of the client response</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">res</span><spanclass="p">.</span><spanclass="nx">writeHead</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">statusCode</span><spanclass="p">,</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">);</span></pre></div></td></tr><trid="section-32"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-32">¶</a></div><p><code>response.statusCode === 304</code>: No 'data' event and no 'end'</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">statusCode</span><spanclass="o">===</span><spanclass="mi">304</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-33"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-33">¶</a></div><p>Set the headers of the client response</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">res</span><spanclass="p">.</span><spanclass="nx">writeHead</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">statusCode</span><spanclass="p">,</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">);</span></pre></div></td></tr><trid="section-34"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-34">¶</a></div><p><code>response.statusCode === 304</code>: No 'data' event and no 'end'</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">statusCode</span><spanclass="o">===</span><spanclass="mi">304</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-33"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-33">¶</a></div><p>For each data <code>chunk</code> received from the <code>reverseProxy</code>
<spanclass="p">}</span></pre></div></td></tr><trid="section-35"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-35">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nx">response</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">chunk</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-34"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-34">¶</a></div><p>When the <code>reverseProxy</code><code>response</code> ends, end the
<spanclass="p">});</span></pre></div></td></tr><trid="section-36"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-36">¶</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
</pre></div></td></tr><trid="section-35"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-35">¶</a></div><p>Emit the <code>end</code> event now that we have completed proxying</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">self</span><spanclass="p">.</span><spanclass="nx">emit</span><spanclass="p">(</span><spanclass="s1">'end'</span><spanclass="p">,</span><spanclass="nx">req</span><spanclass="p">,</span><spanclass="nx">res</span><spanclass="p">);</span>
</pre></div></td></tr><trid="section-37"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-37">¶</a></div><p>Emit the <code>end</code> event now that we have completed proxying</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">self</span><spanclass="p">.</span><spanclass="nx">emit</span><spanclass="p">(</span><spanclass="s1">'end'</span><spanclass="p">,</span><spanclass="nx">req</span><spanclass="p">,</span><spanclass="nx">res</span><spanclass="p">);</span>
<spanclass="p">}</span>
<spanclass="p">});</span>
<spanclass="p">});</span>
</pre></div></td></tr><trid="section-36"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-36">¶</a></div><p>Handle 'error' events from the <code>reverseProxy</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">once</span><spanclass="p">(</span><spanclass="s1">'error'</span><spanclass="p">,</span><spanclass="nx">proxyError</span><spanclass="p">);</span>
</pre></div></td></tr><trid="section-37"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-37">¶</a></div><p>For each data <code>chunk</code> received from the incoming
</pre></div></td></tr><trid="section-38"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-38">¶</a></div><p>Handle 'error' events from the <code>reverseProxy</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">once</span><spanclass="p">(</span><spanclass="s1">'error'</span><spanclass="p">,</span><spanclass="nx">proxyError</span><spanclass="p">);</span>
</pre></div></td></tr><trid="section-39"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-39">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">chunk</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-38"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-38">¶</a></div><p>When the incoming <code>req</code> ends, end the corresponding <code>reverseProxy</code>
<spanclass="p">});</span></pre></div></td></tr><trid="section-40"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-40">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'end'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">()</span><spanclass="p">{</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-39"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-39">¶</a></div><p>If we have been passed buffered data, resume it.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">buffer</span><spanclass="o">&&</span><spanclass="o">!</span><spanclass="nx">errState</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-41"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-41">¶</a></div><p>If we have been passed buffered data, resume it.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">buffer</span><spanclass="o">&&</span><spanclass="o">!</span><spanclass="nx">errState</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-40"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-40">¶</a></div><h3>@private function _forwardRequest (req)</h3>
</pre></div></td></tr><trid="section-42"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-42">¶</a></div><h3>@private function _forwardRequest (req)</h3>
<h4>@req {ServerRequest} Incoming HTTP Request to proxy.</h4>
...
...
@@ -371,25 +390,26 @@ by <code>this.forward</code> ignoring errors and the subsequent response.</p>
</pre></div></td></tr><trid="section-41"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-41">¶</a></div><p>Force the <code>connection</code> header to be 'close' until
</pre></div></td></tr><trid="section-43"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-43">¶</a></div><p>Force the <code>connection</code> header to be 'close' until
</pre></div></td></tr><trid="section-42"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-42">¶</a></div><p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">forwardProxy</span><spanclass="o">=</span><spanclass="nx">protocol</span><spanclass="p">.</span><spanclass="nx">request</span><spanclass="p">(</span><spanclass="nx">outgoing</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-43"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-43">¶</a></div><p>Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy.
</pre></div></td></tr><trid="section-44"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-44">¶</a></div><p>Open new HTTP request to internal resource with will act as a reverse proxy pass</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">forwardProxy</span><spanclass="o">=</span><spanclass="nx">protocol</span><spanclass="p">.</span><spanclass="nx">request</span><spanclass="p">(</span><spanclass="nx">outgoing</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">response</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-45"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-45">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="p">});</span>
</pre></div></td></tr><trid="section-44"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-44">¶</a></div><p>Add a listener for the connection timeout event.</p>
</pre></div></td></tr><trid="section-46"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-46">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nx">forwardProxy</span><spanclass="p">.</span><spanclass="nx">once</span><spanclass="p">(</span><spanclass="s1">'error'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">err</span><spanclass="p">)</span><spanclass="p">{</span><spanclass="p">});</span></pre></div></td></tr><trid="section-45"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-45">¶</a></div><p>Chunk the client request body as chunks from the proxied request come in</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">chunk</span><spanclass="p">)</span><spanclass="p">{</span>
forward target doesn't exist.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">forwardProxy</span><spanclass="p">.</span><spanclass="nx">once</span><spanclass="p">(</span><spanclass="s1">'error'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">err</span><spanclass="p">)</span><spanclass="p">{</span><spanclass="p">});</span></pre></div></td></tr><trid="section-47"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-47">¶</a></div><p>Chunk the client request body as chunks from the proxied request come in</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">chunk</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="p">})</span></pre></div></td></tr><trid="section-46"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-46">¶</a></div><p>At the end of the client request, we are going to stop the proxied request</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'end'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">()</span><spanclass="p">{</span>
<spanclass="p">})</span></pre></div></td></tr><trid="section-48"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-48">¶</a></div><p>At the end of the client request, we are going to stop the proxied request</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'end'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">()</span><spanclass="p">{</span>
<spanclass="kd">var</span><spanclass="nx">self</span><spanclass="o">=</span><spanclass="k">this</span><spanclass="p">,</span><spanclass="nx">outgoing</span><spanclass="p">,</span><spanclass="nx">errState</span><spanclass="o">=</span><spanclass="kc">false</span><spanclass="p">,</span><spanclass="nx">CRLF</span><spanclass="o">=</span><spanclass="s1">'\r\n'</span><spanclass="p">;</span></pre></div></td></tr><trid="section-47"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-47">¶</a></div><p>WebSocket requests has method = GET</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">method</span><spanclass="o">!==</span><spanclass="s1">'GET'</span><spanclass="o">||</span><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">.</span><spanclass="nx">upgrade</span><spanclass="p">.</span><spanclass="nx">toLowerCase</span><spanclass="p">()</span><spanclass="o">!==</span><spanclass="s1">'websocket'</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-48"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-48">¶</a></div><p>This request is not WebSocket request</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">return</span><spanclass="p">;</span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-49"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-49">¶</a></div><p>Turn of all bufferings
<spanclass="kd">var</span><spanclass="nx">self</span><spanclass="o">=</span><spanclass="k">this</span><spanclass="p">,</span><spanclass="nx">outgoing</span><spanclass="p">,</span><spanclass="nx">errState</span><spanclass="o">=</span><spanclass="kc">false</span><spanclass="p">,</span><spanclass="nx">CRLF</span><spanclass="o">=</span><spanclass="s1">'\r\n'</span><spanclass="p">;</span></pre></div></td></tr><trid="section-49"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-49">¶</a></div><p>WebSocket requests has method = GET</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">method</span><spanclass="o">!==</span><spanclass="s1">'GET'</span><spanclass="o">||</span><spanclass="nx">req</span><spanclass="p">.</span><spanclass="nx">headers</span><spanclass="p">.</span><spanclass="nx">upgrade</span><spanclass="p">.</span><spanclass="nx">toLowerCase</span><spanclass="p">()</span><spanclass="o">!==</span><spanclass="s1">'websocket'</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-50"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-50">¶</a></div><p>This request is not WebSocket request</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">return</span><spanclass="p">;</span>
<spanclass="p">}</span>
</pre></div></td></tr><trid="section-51"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-51">¶</a></div><p>Turn of all bufferings
For server set KeepAlive
For client set encoding</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="kd">function</span><spanclass="nx">_socket</span><spanclass="p">(</span><spanclass="nx">socket</span><spanclass="p">,</span><spanclass="nx">keepAlive</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-50"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-50">¶</a></div><p>We're now connected to the server, so lets change server socket</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">proxySocket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="nx">listeners</span><spanclass="p">.</span><spanclass="nx">_r_data</span><spanclass="o">=</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">data</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-51"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-51">¶</a></div><p>Pass data to client</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">incoming</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">writable</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-52"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-52">¶</a></div><p>We're now connected to the server, so lets change server socket</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">proxySocket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="nx">listeners</span><spanclass="p">.</span><spanclass="nx">_r_data</span><spanclass="o">=</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">data</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-53"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-53">¶</a></div><p>Pass data to client</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">incoming</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">writable</span><spanclass="p">)</span><spanclass="p">{</span>
@@ -426,19 +446,19 @@ For client set encoding</p> </td> <td class="code">
<spanclass="p">}</span>
<spanclass="p">});</span>
<spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">incoming</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="nx">listeners</span><spanclass="p">.</span><spanclass="nx">_data</span><spanclass="o">=</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">data</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-52"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-52">¶</a></div><p>Pass data from client to server</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">try</span><spanclass="p">{</span>
<spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">incoming</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="nx">listeners</span><spanclass="p">.</span><spanclass="nx">_data</span><spanclass="o">=</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">data</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-54"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-54">¶</a></div><p>Pass data from client to server</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">try</span><spanclass="p">{</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-53"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-53">¶</a></div><p>Detach event listeners from reverseProxy</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="kd">function</span><spanclass="nx">detach</span><spanclass="p">()</span><spanclass="p">{</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-55"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-55">¶</a></div><p>Detach event listeners from reverseProxy</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="kd">function</span><spanclass="nx">detach</span><spanclass="p">()</span><spanclass="p">{</span>
<spanclass="p">};</span></pre></div></td></tr><trid="section-58"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-58">¶</a></div><p>Make the outgoing WebSocket request</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="kd">var</span><spanclass="nx">reverseProxy</span><spanclass="o">=</span><spanclass="nx">agent</span><spanclass="p">.</span><spanclass="nx">appendMessage</span><spanclass="p">(</span><spanclass="nx">outgoing</span><spanclass="p">);</span></pre></div></td></tr><trid="section-59"><tdclass="docs"><divclass="pilwrap"><aclass="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
<spanclass="p">};</span></pre></div></td></tr><trid="section-60"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-60">¶</a></div><p>Make the outgoing WebSocket request</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="kd">var</span><spanclass="nx">reverseProxy</span><spanclass="o">=</span><spanclass="nx">agent</span><spanclass="p">.</span><spanclass="nx">appendMessage</span><spanclass="p">(</span><spanclass="nx">outgoing</span><spanclass="p">);</span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-61"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-61">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">agent</span><spanclass="o">=</span><spanclass="nx">agent</span><spanclass="p">;</span>
...
...
@@ -470,52 +499,45 @@ in nodejs core and is <strong>very</strong> specific to proxying WebSockets.</p>
</pre></div></td></tr><trid="section-60"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-60">¶</a></div><p>If the agent for this particular <code>host</code> and <code>port</code> combination
</pre></div></td></tr><trid="section-62"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-62">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="o">!</span><spanclass="nx">agent</span><spanclass="p">.</span><spanclass="nx">_events</span><spanclass="o">||</span><spanclass="nx">agent</span><spanclass="p">.</span><spanclass="nx">_events</span><spanclass="p">[</span><spanclass="s1">'upgrade'</span><spanclass="p">].</span><spanclass="nx">length</span><spanclass="o">===</span><spanclass="mi">0</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="nx">agent</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'upgrade'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">_</span><spanclass="p">,</span><spanclass="nx">remoteSocket</span><spanclass="p">,</span><spanclass="nx">head</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-61"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-61">¶</a></div><p>Prepare the socket for the reverseProxy request and begin to
stream data between the two sockets</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">_socket</span><spanclass="p">(</span><spanclass="nx">remoteSocket</span><spanclass="p">,</span><spanclass="kc">true</span><spanclass="p">);</span>
<spanclass="nx">agent</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'upgrade'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="p">(</span><spanclass="nx">_</span><spanclass="p">,</span><spanclass="nx">remoteSocket</span><spanclass="p">,</span><spanclass="nx">head</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-63"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-63">¶</a></div><p>Prepare the socket for the reverseProxy request and begin to
stream data between the two sockets. Here it is important to
note that <code>remoteSocket._httpMessage === reverseProxy</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">_socket</span><spanclass="p">(</span><spanclass="nx">remoteSocket</span><spanclass="p">,</span><spanclass="kc">true</span><spanclass="p">);</span>
</pre></div></td></tr><trid="section-62"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-62">¶</a></div><p>If the reverseProxy connection has an underlying socket,
</pre></div></td></tr><trid="section-64"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-64">¶</a></div><p>If the reverseProxy connection has an underlying socket,
then behing the handshake.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="k">typeof</span><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="o">!==</span><spanclass="s1">'undefined'</span><spanclass="p">)</span><spanclass="p">{</span>
<spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="nx">handshake</span><spanclass="p">(</span><spanclass="nx">data</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-63"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-63">¶</a></div><p>Ok, kind of harmfull part of code. Socket.IO sends a hash
<spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="kd">function</span><spanclass="nx">handshake</span><spanclass="p">(</span><spanclass="nx">data</span><spanclass="p">)</span><spanclass="p">{</span></pre></div></td></tr><trid="section-65"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-65">¶</a></div><p>Ok, kind of harmfull part of code. Socket.IO sends a 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><tdclass="code"><divclass="highlight"><pre><spanclass="kd">var</span><spanclass="nx">sdata</span><spanclass="o">=</span><spanclass="nx">data</span><spanclass="p">.</span><spanclass="nx">toString</span><spanclass="p">();</span></pre></div></td></tr><trid="section-64"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-64">¶</a></div><p>Get the Printable data</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">sdata</span><spanclass="o">=</span><spanclass="nx">sdata</span><spanclass="p">.</span><spanclass="nx">substr</span><spanclass="p">(</span><spanclass="mi">0</span><spanclass="p">,</span><spanclass="nx">sdata</span><spanclass="p">.</span><spanclass="nx">search</span><spanclass="p">(</span><spanclass="nx">CRLF</span><spanclass="o">+</span><spanclass="nx">CRLF</span><spanclass="p">));</span></pre></div></td></tr><trid="section-65"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-65">¶</a></div><p>Get the Non-Printable data</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">data</span><spanclass="o">=</span><spanclass="nx">data</span><spanclass="p">.</span><spanclass="nx">slice</span><spanclass="p">(</span><spanclass="nx">Buffer</span><spanclass="p">.</span><spanclass="nx">byteLength</span><spanclass="p">(</span><spanclass="nx">sdata</span><spanclass="p">),</span><spanclass="nx">data</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="p">);</span></pre></div></td></tr><trid="section-66"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-66">¶</a></div><p>Replace the host and origin headers in the Printable data</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">sdata</span><spanclass="o">=</span><spanclass="nx">sdata</span><spanclass="p">.</span><spanclass="nx">replace</span><spanclass="p">(</span><spanclass="nx">remoteHost</span><spanclass="p">,</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">host</span><spanclass="p">)</span>
will come after double-CRLF).</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="kd">var</span><spanclass="nx">sdata</span><spanclass="o">=</span><spanclass="nx">data</span><spanclass="p">.</span><spanclass="nx">toString</span><spanclass="p">();</span></pre></div></td></tr><trid="section-66"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-66">¶</a></div><p>Get the Printable data</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">sdata</span><spanclass="o">=</span><spanclass="nx">sdata</span><spanclass="p">.</span><spanclass="nx">substr</span><spanclass="p">(</span><spanclass="mi">0</span><spanclass="p">,</span><spanclass="nx">sdata</span><spanclass="p">.</span><spanclass="nx">search</span><spanclass="p">(</span><spanclass="nx">CRLF</span><spanclass="o">+</span><spanclass="nx">CRLF</span><spanclass="p">));</span></pre></div></td></tr><trid="section-67"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-67">¶</a></div><p>Get the Non-Printable data</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">data</span><spanclass="o">=</span><spanclass="nx">data</span><spanclass="p">.</span><spanclass="nx">slice</span><spanclass="p">(</span><spanclass="nx">Buffer</span><spanclass="p">.</span><spanclass="nx">byteLength</span><spanclass="p">(</span><spanclass="nx">sdata</span><spanclass="p">),</span><spanclass="nx">data</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="p">);</span></pre></div></td></tr><trid="section-68"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-68">¶</a></div><p>Replace the host and origin headers in the Printable data</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">sdata</span><spanclass="o">=</span><spanclass="nx">sdata</span><spanclass="p">.</span><spanclass="nx">replace</span><spanclass="p">(</span><spanclass="nx">remoteHost</span><spanclass="p">,</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">host</span><spanclass="p">)</span>
<spanclass="k">try</span><spanclass="p">{</span></pre></div></td></tr><trid="section-67"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-67">¶</a></div><p>Write the printable and non-printable data to the socket
<spanclass="k">try</span><spanclass="p">{</span></pre></div></td></tr><trid="section-69"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-69">¶</a></div><p>Write the printable and non-printable data to the socket
from the original incoming request. </p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="p">(</span><spanclass="nx">sdata</span><spanclass="p">);</span>
<spanclass="p">});</span></pre></div></td></tr><trid="section-69"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-69">¶</a></div><p>Remove data listener now that the 'handshake' is complete</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">removeListener</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="nx">handshake</span><spanclass="p">);</span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-70"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-70">¶</a></div><p>Catch socket errors</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">on</span><spanclass="p">(</span><spanclass="s1">'error'</span><spanclass="p">,</span><spanclass="nx">proxyError</span><spanclass="p">);</span></pre></div></td></tr><trid="section-71"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-71">¶</a></div><p>Remove data listener now that the 'handshake' is complete</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">socket</span><spanclass="p">.</span><spanclass="nx">removeListener</span><spanclass="p">(</span><spanclass="s1">'data'</span><spanclass="p">,</span><spanclass="nx">handshake</span><spanclass="p">);</span>
<spanclass="k">try</span><spanclass="p">{</span></pre></div></td></tr><trid="section-70"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-70">¶</a></div><p>Attempt to write the upgrade-head to the reverseProxy request.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="p">(</span><spanclass="nx">head</span><spanclass="p">);</span>
<spanclass="k">try</span><spanclass="p">{</span></pre></div></td></tr><trid="section-72"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-72">¶</a></div><p>Attempt to write the upgrade-head to the reverseProxy request.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">reverseProxy</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="p">(</span><spanclass="nx">head</span><spanclass="p">);</span>
</pre></div></td></tr><trid="section-71"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-71">¶</a></div><p>If we have been passed buffered data, resume it.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">buffer</span><spanclass="o">&&</span><spanclass="o">!</span><spanclass="nx">errState</span><spanclass="p">)</span><spanclass="p">{</span>
</pre></div></td></tr><trid="section-73"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-73">¶</a></div><p>If we have been passed buffered data, resume it.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="p">(</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">buffer</span><spanclass="o">&&</span><spanclass="o">!</span><spanclass="nx">errState</span><spanclass="p">)</span><spanclass="p">{</span>