I recently had the issue where I needed to proxy traffic from my IP address to a different server, in order to perform mobile testing. The setup I have is a "local" server running on my development machine with a local hostname, since my phone can not access this hostname, I decided to use a proxy that allows me to visit the IP address of my development machine on my phone and all traffic would forward to the local domain.

I decided to use Express.JS as it is an easy to use server. Express also has large amount of community contributed middlewares, such as express-http-proxy which fills all of my requirements.

Additionally I use the package "ip" that will discover the local IP address of my development machine.

These dependencies can be installed with:

yarn add express express-http-proxy ip

The proxy server is quite small, and looks as follows:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

const ip = require('ip');
const proxy = require('express-http-proxy');
const app = require('express')();

const port = 8888;
const proxyHostname = process.argv[2];
const proxyURL = `https://${proxyHostname}/`;
const ipAddress = ip.address();
const serverURL = `http://${ipAddress}:${port}/`;

app.use(
  '/',
  proxy(proxyHostname, {
    https: true,

    userResDecorator: function(_proxyRes, proxyResData) {
      let html = proxyResData.toString('utf8');

      html = html.replace(new RegExp(proxyURL, 'g'), serverURL);

      return html;
    }
  })
);

app.listen(port);
console.log(`Proxying all traffic from ${serverURL} to ${proxyURL}`);

Since my local server ("https://my-project.local/") uses HTTPS but with a self generated SSL certificate, the proxy will encounter SSL errors. So the first line of the proxy tells the node process not to crash when this happens.

Next I import ip, proxy and, app from the installed node modules.

Then a few constants are defined to set the port number for the proxy to run on, the server address we want to proxy too, and read the IP address of the development machine. process.argv is used so that you can pass the hostname of the local server to the node process instead of having to hard-code it in the file.

The largest part of this script is then telling express to use the proxy middleware which I configure to proxy all traffic coming in to the server (path /) and proxy it to the local development server. The options passed to proxy tell it that this server uses HTTPS and additionally there is a callback given called userResDecorator.

userResDecorator allows me to intercept the response from the local server before passing it back to the client. In this method what I am doing is replacing all URLs in the returned HTML and rewriting them from the my-project.local to instead use the proxy address. This means all <a> links etc. now point to the correct location.

Finally we tell the express app to listen on our given port and log to the console the address of the proxy that is running.

Now, when I save the script to the file proxy.js run the proxy server with node proxy.js my-project.local, I see a message that my proxy is listening at "http://192.168.1.99:8888/". When I visit this URL on my mobile device, I see my project as if I was visiting from my development machine.

For the full source code, you can find it on GitHub: https://github.com/BlakeSimpson/local-ip-proxy