Question

I want to allow an authenticated client in Express to access to other web applications that are running on the server, but on different ports.

For example, I have express running on http://myDomain and I have another application running on say port 9000. I want to be able to reach the other app through http://myDomain/proxy/9000.

I had a little bit of success using node-http-proxy, for example:

function(req, res) {
  var stripped = req.url.split('/proxy')[1];
  var path = stripped.split('/');
  var port = path.shift();
  var url = path.join('/');

  req.url = url;
  proxy.web(req, res, {
    target: 'http://127.0.0.1:' + port
  });
}

However, the big problem is that when the web app makes GET requests, such as for /js/lib.js, it resolves to http://myDomain/js/lib.js, which is problematic because express is not aware of those assets. The correct request would be to http://myDomain/proxy/9000/js/lib.js. How do I route all these additional requests?

Was it helpful?

Solution

What you need to do is to replace URLs in the initial page with the new URL pattern. What is happening is that the initial page that your reverse proxy returns has a reference to:
/js/lib.js or http://myDomain/js/lib.js
so when the browser makes a second request it has the wrong pattern for your reverse proxy.

Based on the incoming request you know what the pattern should look like. In your example it's http://myDomain/proxy/9000. You then fetch the appropriate page from the other server running on http://127.0.0.1:9000/. You do a string replace on any resources in that file. You'll need to experiment with the pattern but you might look for 'script src="/' or 'href="/' and you might find regex helps with the pattern if, for example, the src attribute isn't the first listed in a script tag.

For example you might find 'scr="/' and then you replace it with 'src="/proxy/9000/' that way when the browser asks for that local resource it will come through with the port that you're looking for. This is going to need experimentation and it's a great algorithm to write unit testing around to get perfect.

Once you've done the replacement you just stream that page to the client. res.send() will do this for you.

Something else that you might find useful is that ExpressJS gives you a way to pull out the port number with a little less hassle than you're doing. Take a look at this example:

app.get('/proxy/:port', function(req, res){
    console.log('port is ' + req.params.port);
});

OTHER TIPS

I don't think http://myDomain/proxy/9000 is the correct way to do it. Web pages are going to assume the site's domain to be just myDomain and not myDomain/proxy/9000, because that is what the standard says.

Your use case would be better served by using subdomains like 9000.proxy.myDomain.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top