javascriptnode.jshttp-proxynode-http-proxy

Forward every request with node-http-proxy


I'm trying to setup a node-http-proxy that just forwards requests. In the end this proxy should inject javascript in every website I visit through the browser..

Right now, most pages are forwarded and displayed correctly, but some, like posterkoenig.ch or verkehrsclub.ch are returning either a blank page or there is an error on the page. Both sites work well without the proxy in place. What do I have to change, or what am I missing that gets not forwarded correctly?

Im very new to nodejs and not even completely sure if my approach should work or not.

Here is what I've got so far:

var httpProxy = require('http-proxy');
var url = require('url');

httpProxy.createServer(function(req, res, proxy) {

  var urlObj = url.parse(req.url);

  proxy.proxyRequest(req, res, {
    host: urlObj.host,
    port: 80,
    changeOrigin: true,
    enable : { xforward: true }
  });
}).listen(9000, function () {
  console.log("Waiting for requests...");
});

Update

As suggested by @robertklep I removed changeOrigin and redefined req.headers.host and also req.headers.url

posterkoenig.ch:

Now throws:

An error has occurred: 
{"code":"ENOTFOUND","errno":"ENOTFOUND","syscall":"getaddrinfo"}

verkehrsclub.ch:

The frontpage works now but subpages still throw a error on the page.

var httpProxy = require('http-proxy');
var url = require('url');

httpProxy.createServer(function(req, res, proxy) {

  var urlObj = url.parse(req.url);

  req.headers['host'] = urlObj.host;
  req.headers['url'] = urlObj.href;

  proxy.proxyRequest(req, res, {
    host: urlObj.host,
    port: 80,
    enable : { xforward: true }
  });
}).listen(9000, function () {
  console.log("Waiting for requests...");
});

Solution

  • Your first problem is related to changeOrigin: that will send a Host header to the remote server which includes a port number, and both sites you mention can't handle that.

    Instead, try this:

    req.headers.host = urlObj.host;
    req.url          = urlObj.path;
    proxy.proxyRequest(req, res, {
      host: urlObj.host,
      port: 80,
      enable : { xforward: true }
    });
    

    As for your other problem, I think it might be related to websites that don't serve their content as UTF-8 (which is the encoding that .toString() will use if you don't pass it an encoding). Does it happen always, or just with some sites?

    FWIW, harmon is a middleware for node-http-proxy which provides a nice way of rewriting responses. It might be an overkill for your situation, but it might also solve your problem.

    EDIT: here's a minimal example that seems to work just fine for both posterkoenig.ch and www.verkehrsclub.ch (homepages as well as subpages):

    var httpProxy = require('http-proxy');
    var url       = require('url');
    
    httpProxy.createServer(function(req, res, proxy) {
      var urlObj = url.parse(req.url);
    
      req.headers.host  = urlObj.host;
      req.url           = urlObj.path;
    
      proxy.proxyRequest(req, res, {
        host    : urlObj.host,
        port    : 80,
        enable  : { xforward: true }
      });
    }).listen(9000, function () {
      console.log("Waiting for requests...");
    });