13

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...");
});
BMW
  • 42,880
  • 12
  • 99
  • 116
greenish
  • 1,042
  • 1
  • 8
  • 18
  • were you able to do this for HTTPS sites? – everconfusedGuy Jul 25 '13 at 03:11
  • Basically it should be possible.. I haven't tried it, but the [documentation of node-http-proxy](https://github.com/nodejitsu/node-http-proxy#using-https) says it supports https. But your node app would have to run an https server as well, so you need a valid https certificate and key to make it work. Then you should be able to use a [slight variation](https://github.com/nodejitsu/node-http-proxy#proxy-requests-within-another-http-server) of the script above with an https server. Hope that helps! – greenish Jul 25 '13 at 12:27
  • How have you configured your browser to use this proxy? Just entered localhost:9000 as the web proxy server address? – Ayush Goel Dec 14 '17 at 21:06

1 Answers1

15

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...");
});
bubakazouba
  • 1,633
  • 2
  • 22
  • 34
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Thanks for your time! I tried this, but when I remove the changeOrigin flag, posterkoenig.ch returns **An error has occurred: {"code":"ENOTFOUND","errno":"ENOTFOUND","syscall":"getaddrinfo"}**. I then also redefined the headers.url.. with this, the verkehrsclub.ch frontpage appears correctly but every subpage is still broken.. I updated my code in the question – greenish May 06 '13 at 13:31
  • The error you're getting for `postkoenig.ch` suggests a DNS error, which is strange (what's the value of `urlObj.host` in that case?). Also, I edited my answer because there's another issue I spotted which might cause your second problem. – robertklep May 06 '13 at 14:56
  • Thanks, the `req.url = urlObj.path;` did the job! – greenish May 07 '13 at 11:05
  • I tried the minimal example, but it only pays attention to requests coming from 127.0.0.1. How do I make it listen to requests coming from an external source as well? – Attila Szeremi Oct 09 '13 at 16:27
  • 1
    @SzerémiAttila I don't think that's something to do with `http-proxy`, I tested it (run the proxy on my Mac, access it via my Linux server) and it works as-is. Perhaps you have a firewall that's blocking incoming connections? – robertklep Oct 09 '13 at 16:46
  • @robertklep it's probably a firewall as I tested on a different server that I had more control over and it worked there. Thanks! – Attila Szeremi Oct 10 '13 at 09:40
  • What url do you hit to make the node proxy code do it's magic? – a_dreb May 20 '16 at 00:50
  • This doesn't work anymore, as now it is mandatory to pass some kind of a target or a forward field in the options. Running the above code gives me Must provide valid url for Target. @greenish – Ayush Goel Dec 15 '17 at 18:48
  • @AyushGoel instead of setting the `host` and `port` options, try using `target : req.url` – robertklep Dec 15 '17 at 18:54
  • No that doesn't work. See [_this_](https://github.com/nodejitsu/node-http-proxy/blob/master/lib/http-proxy/index.js#L67-L69) . `Options` is a dictionary where target/forward is one of the required fields. – Ayush Goel Dec 15 '17 at 19:04
  • I haven't been able to make it work for the life of me. @robertklep. If you have any idea how this can work with the latest library code, can you post the answer [here](https://stackoverflow.com/questions/47821987/forward-http-proxy-using-node-http-proxy). Thanks a lot – Ayush Goel Dec 15 '17 at 19:07