Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect an http request from a remote server to a local server using nodejs

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

like image 803
prashn64 Avatar asked Jan 26 '14 05:01

prashn64


3 Answers

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.

like image 145
Brad Avatar answered Oct 27 '22 21:10

Brad


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.

like image 23
BogdanBiv Avatar answered Oct 27 '22 23:10

BogdanBiv


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.

like image 28
CFrei Avatar answered Oct 27 '22 21:10

CFrei