Total results: 5

Writing a local IP proxy with node.js

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

Serving static files with Server.js

Server.js is a node based server that is based on Express.js but provides you with an even easier interface to write your server with.

As server.js was only recently released, I was trying to find a tutorial on how to serve a directory of static files but could not find one. After reading the documentation, I noticed that since Server.js is built on express, you can use express middlewares out of the box. Since Express already has a express.static() method, I noitced that I could use this to serve static files as I wanted.

The example server is very basic, it simply serves all files in the current directory.

First of all, I import server and express:

const server = require('server');
const express = require('express');

Next I import the modern method from server.utils that allows us to attach Express middleware to our server:

const { modern } = server.utils;

I then call the express.static middleware, and pass it to modern:

const middleware = modern(express.static('./'));

Finally, I start the server and pass the static middleware:

server(middleware);

The final server is only 7 lines long:

const server = require('server');
const express = require('express');
const { modern } = server.utils;

const middleware = modern(express.static('./'));

server(middleware);

You can test this by writing this to a file called server.js and calling it with node server.js. The server will then be running at: http://localhost:3000/.

If you then write an index.html file in the same directory, it will be served when visiting this address in your browser.

For full example code, please visit this repo: https://github.com/BlakeSimpson/serverjs-static-files

Ember Server "Bus Error 10" Fix

If you are using the ember-cli package to access the ember command line tool and experience a "Bus Error 10" that crashes the ember server every time you save a file then it is probably due to an incompatible Node.js version.

To fix this issue simply head to the Node.js downloads page and get the latest version of Node for your operating system.

For a functional ember server you should be using Node.js version 0.10.21 or higher, personally I upgraded from 0.10.20 to 0.10.29 and now the server runs perfectly, including the live reload functionality.

Static file web servers

Testing a static website can be done simply by opening the HTML files in a web browser, but for some functionality to perform correctly, such as local AJAX calls, the files need to be served from a web server.

Alternatively, you may want to check out some static files on your mobile device. You can do this easily by starting a simple web server for the project and navigate to your computers IP address with the given server port.

Python Server

The easiest way to do this on UNIX based systems is to use the Python Simple HTTP Server, like so:

python -m SimpleHTTPServer 8080

Run this command in the same directory as your project from the terminal, then point your browser to http://localhost:8080.

This is a great way to get a server running in seconds, for basic testing, but I have found that as the number of files in the project increases, the stability of the server decreases. Often files will not be passed to the client and 404 errors are encountered. For these reasons I have investigated a stronger solution that is still simple to setup. This leads me to Node.JS.

Node Server

Node.JS is no stranger to web servers, in fact this is often the primary task of a Node application.

"Connect" is a Node.JS middleware application that makes the creation of simple web servers trivial.

To get Connect running, first install it via npm:

npm install -g connect

Here is a web server that can be used, simply paste the code into a file called "server.js" in your project's root directory.

var connect = require( 'connect' ),
  http = require( 'http' );

app = connect()
  .use( connect.logger( 'dev' ) )
  .use( connect.static( __dirname ) );

http.createServer( app ).listen( 8080 );

Finally run the server from the terminal like so:

node server.js

If no error was received, the server is running and files can be viewed by browsing http://localhost:8080, just like in the Python example.

I have not had any trouble with the Connect version of my server and it comes built with a nice development logger, showing what files were requested and with what status. This output can be viewed live in the terminal window as requests come in.

Connect Server Dev Log

Install Node.JS on Debian Wheezy

Official Method

The official Node.JS install guide recommends manually downloading and building the Node.JS package for Debian. This can be done using the following set of commands:

sudo apt-get install python g++ make checkinstall
mkdir ~/node_js_src && cd $_
wget -N http://nodejs.org/dist/node-latest.tar.gz
tar xzvf node-latest.tar.gz && cd node-v*
./configure
checkinstall
sudo dpkg -i node_*

This install method should work fine but will take a long time to complete on the Raspberry Pi's hardware. For this reason I experimented a little and found a quicker install method that doesn't require a manual compile, by using the Ubuntu package.

Ubuntu Method

This install method will be much faster than the official method but is not designed for Debian Wheezy, so use at your own risk! Personally I have not had any trouble with my node install yet but I cannot guarantee this will be the case for anyone else.

sudo apt-get update
sudo apt-get install -y python-software-properties python g++ make
sudo add-apt-repository ppa:chris-lea/node.js

At this point the file with the new repository details must be edited. Open the file: /etc/apt/sources.list.d/chris-lea-node_js-wheezy.list with a text editor like vim and change the word "wheezy" to "lucid". Thanks to Ken Yap for this hint.

Now, go on and finish installing Node.

sudo apt-get update
sudo apt-get install -y nodejs

© Blake Simpson, 2012 – 2017