Node-http-proxy: Document `forward` vs. `target`

Created on 11 Feb 2015  路  8Comments  路  Source: http-party/node-http-proxy

After reading the docs and examples, the purpose and distinction between forward and target is still not clear to me (including forward-and-target-proxy.js example - I can't tell what this is actually demonstrating). After implementing a very simple single-step target proxy behind Express, I wanted to place a transparent forward proxy in between Node and backend server in order to cache some large, expensive API requests. I was not successful with any permutation of forward or target options. My intuition was that target would be used to "fix up" the outbound request (setupOutgoing), while forward would be the immediate server to hand off to (the local caching proxy). It appears that changeOrigin will use the forward host, not the target host. This is likely due to logic in stream and setupOutgoing that appears to modify the request for both cases. I'm not sure I understand the precedence of the piping. Also forward will not convert a relative path request to an absolute URL request required by an upstream transparent HTTP proxy.

It would be nice to have a some more docs on how to use forward and target in combination or separately, and whether handoff to transparent proxy is supported out of the box (e.g. inference from combination of forward and target would be nice).

I managed to manually perform these fixups when in 'transparent handoff' mode as advised on StackOverflow:

opts = target: remoteServer

if process.argv[2]?
  localProxy = process.argv[2]
  opts.forward = localProxy
  opts.toProxy = true
  opts.prependPath = false # fix it up ourselves

console.log "Proxying #{apiRoot} to #{remoteServer}" + (if localProxy? then " via #{localProxy}" else "")

proxy = httpProxy.createProxyServer opts
app.use apiRoot, (req, res, next) ->
  console.log "Proxying: #{req.method} #{req.path} to #{remoteServer}"
  console.log "Original URL #{req.url}"
  console.log "Original Host #{req.headers.host}"
  # explicitly fix up host and request url if forwarding to local proxy
  if localProxy?
    remote = url.parse(remoteServer)
    incoming = url.parse(req.url)
    req.headers.host  = remote.host
    # update the host and path to match remote target
    incoming.protocol = remote.protocol
    incoming.host = remote.host
    incoming.pathname = remote.pathname + incoming.pathname
    req.url = url.format(incoming)
    console.log "Outbound Host #{req.headers.host}"
    console.log "Outbound URL #{req.url}"

    proxy.web req, res, (e) ->
      console.log e

Most helpful comment

+1 on putting this:

  *  target === final server to receive request
  *  forward === another proxy server to pass request through

in the readme.

All 8 comments

Citation from damonmcminn's an answer;

http.createServer(function(req, res) {
  /* target NOT forward
  *  target === final server to receive request
  *  forward === another proxy server to pass request through
  */
  var options = {
    target: targets[req.headers.host]
  };
  proxy.web(req, res, options, errorCallback); // errorCallback is optional
}).listen(1443);

+1, the documentation should definitely explain the difference between target and forward.

+1 on putting this:

  *  target === final server to receive request
  *  forward === another proxy server to pass request through

in the readme.

https://github.com/nodejitsu/node-http-proxy/issues/917
yuuup, still really unclear and missing from the doc.

I had to look to find this post, it's istll unclear in the doc right now.

it's 2018.9.12

It seems "forward" does not send the response back to the requesting side. In fact, docs says exactly that:

  /**
   * Does the actual proxying. If `forward` is enabled fires up
   * a ForwardStream, same happens for ProxyStream. **The request
   * just dies otherwise.**
   *
   * @param {ClientRequest} Req Request object
   *聽@param {IncomingMessage} Res Response object
   * @param {Object} Options Config object passed to the proxy
   *
   * @api private
   */

  stream: function stream(req, res, options, _, server, clb) {

Note, the The request just dies otherwise.

Source code follows the docs (from /node-http-proxy/lib/http-proxy/passes/web-incoming.js):

    if(options.forward) {
      // If forward enable, so just pipe the request
      ...
      if(!options.target) { return res.end(); }
    }

Note, the return res.end(). The empty response is sent back.

It seems, when one need to forward the request to another proxy, that proxy should still be specified in the "target" field. The "changeOrigin" should be set to "false". The "toProxy" option didn't make any difference in my experiments, but keeping it in "true" did not harm.

The intention of the "forward" option is still very much unclear.

2020.05.29 it's still unclear

Was this page helpful?
0 / 5 - 0 ratings

Related issues

damianchojna picture damianchojna  路  5Comments

jnjnljljjsw picture jnjnljljjsw  路  6Comments

jsmylnycky picture jsmylnycky  路  3Comments

adi518 picture adi518  路  3Comments

tbc1 picture tbc1  路  4Comments