5

There is a feature in a tool called charles that allows you to map remote requests:

http://www.charlesproxy.com/documentation/tools/map-remote/

Basically, it can take any request to a server(even if you're not the one running it) and then makes a new request to another server, preserving the path and the query string. The response from the second server then overwrites the response from the first server.

I just want to know if there is a node module that can do this. I tried using http-proxy, but I have a feeling this map remote tool is a bit different than a proxy, since it seems like you must own both servers with a proxy.

EDIT: Tried using the http-proxy node module again, but can't seem to get it to work. Here's my code:

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

httpProxy.createServer({
    hostnameOnly: true,
    router: {
        'www.stackoverflow.com': 'localhost:9000',
    }
}).listen(80);

// Create your target server
//
http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

My expectation is that when I go to www.stackoverflow.com or www.stackoverflow.com:80, it will instead redirect to my localhost:9000

prashn64
  • 657
  • 1
  • 8
  • 24

4 Answers4

4

No, what you are asking for is indeed a simple proxy. And no, you don't have to "own" both servers to run a proxy. You simply proxy the request, and at that point you can modify the data however you wish.

The proxy module you mention will work fine, and there are many others. You can also do this with simple Nginx config if you wish.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • I researched a little more, and wouldn't this be more than a simple proxy, but instead a reverse proxy? – prashn64 Jan 27 '14 at 07:22
  • 4
    @prashn64 Nope, just a proxy server. The truth is, the term "reverse proxy" is almost meaningless anyway. Usually the term is used when you are putting a proxy server next to your servers to load balance (among other things). It's all just a proxy server though. You've added more information to your question... have you set up a hosts file entry pointing `www.stackoverflow.com` to whatever IP your Node.js server has? – Brad Jan 27 '14 at 13:43
  • If it's possible, I'd prefer not to have to change a config for this. Shouldn't a routing table handle this anyway? – prashn64 Jan 29 '14 at 00:36
  • 1
    You're confusing some things here. Routing tables do nothing but set up routes between IP networks. This has absolutely nothing to do with DNS resolution. If you want your server to handle traffic for www.stackoverflow.com, then www.stackoverflow.com must resolve to the IP address of your server. You can either configure your DNS server (if you want this change to work with many), or set up a hosts file entry (which overrides DNS). Alternatively, set up a regular proxy in your server, and change your computer's proxy settings to use it. How do you think Charles works, anyway? – Brad Jan 29 '14 at 02:24
  • Ahh ok, that makes sense. I am actually completely in the dark as to how Charles work, and is a black box at the moment for me. So it sounds like the only option that will make this work on any computer with just a single node server command would be setting up the DNS server with the correct configuration? Do you know if I would need another node module on top to handle this? – prashn64 Jan 31 '14 at 23:45
  • 1
    @prashn64 Charles is just a proxy server. When you run it, it sets itself as the system proxy server. If you want other machines to use your proxy server, you must configure them. If you want your machine to use alternate servers for some addresses without a proxy, you must reconfigure whatever DNS server they use. This has nothing to do with your application... it depends on the DNS server. It isn't clear to me at all at this point what you are trying to do. – Brad Feb 01 '14 at 06:48
3

I made this pastebin with my solution: http://pastebin.com/TfG67j1x

Save the content of the pastebin as proxy.js. Make sure you install dependencies in the same folder as the proxy.js file. (npm install http-proxy colors connect util --save)

When you run the proxy, it will:

  • start a new server listening on 8013, acting as a proxy server;
  • start a demo target server listening at 9013.

When accessing the demo target through the proxy, it modifies the "Ruby" string into "nodejitsu", for easy testing. If you are behind a corporate firewall/proxy, this script fails for now.

UPDATE: The problem with "headers already sent" was at line 32/33. It turns out that several errors occured on the same connection. When first error occurs, headers would be sent, when second error occurs, headers are already sent; as a result a "headers already sent" exception is raised and the server is killed.

With this fix the server no longer dies, but it still does not fix the source of the error, which is that NODE.JS cannot reach your target site. You must be behind another proxy/firewall and NodeJS would need to forward the HTTP request to a second proxy. If you normally use a proxy in your Browser to connect to Internet, my solution will fail. You did not specify this to be a requirement, though.

You may verify this by accessing through my proxy a server inside your network (no proxy required for it normally).

UPDATE2: You should not try to access http://localhost:8013 directly, but to set it as a proxy in your browser. Take notice of your original browser proxy settings (see above). Try and access then http://localhost:9013.

BogdanBiv
  • 1,485
  • 1
  • 16
  • 33
  • 1
    I'm getting this error: `http.js:645 throw new Error('Can\'t set headers after they are sent.');` Is that because of a firewall issue? – prashn64 Feb 03 '14 at 07:03
  • ^That's when I try to connect to localhost:8013 btw. – prashn64 Feb 03 '14 at 07:17
  • I tried your updates and indeed don't get those errors anymore. However, I still don't get the altered "Ruby" -> "nodejitsu" text change. Also, when I hit stackoverflow.com, I don't get redirected to localhost:9013. I checked my browser proxy and nothing seemed to be set up. – prashn64 Feb 04 '14 at 23:33
  • Proxy servers work when they are set up as middlemen between your browser and the server you are accessing. You have to set up your browser to use the proxy server at localhost:8013 before accessing stackoverflow.com, otherwise you'll see the normal browser behaviour. You seem to be confusing the way proxy servers work with the HTTP url redirect works (http://stackoverflow.com/questions/5411538/how-to-redirect-from-an-html-page). With proxy set, browser will behave as the content really came directly from webserver, the redirection will not be visible in GUI (i.e. URL in address wont change). – BogdanBiv Feb 06 '14 at 06:24
  • Long time, no see... I still don't know if my answers actually helped you in any way. – BogdanBiv Feb 06 '14 at 18:13
  • I still have to check and see if setting the browser to use the proxy server will work. Will have some time over the weekend to check it out. – prashn64 Feb 06 '14 at 21:25
1

Did you add that proxy to your browser config? Otherwise the underlying OS would route your request directly to www.stackoverflow.com and there is no way your proxy is catching that.

CFrei
  • 3,552
  • 1
  • 15
  • 29
1

Could you confirm that www.stackoverflow.com is ending up at your node.app at all? The name currently will resolve to the IP address that leads you to this website, so you would have to have made sure that name now resolves to your node.app. In this case, that probably means editing your hosts file.

Spork
  • 1,631
  • 1
  • 21
  • 37