Understanding Express Middleware in Node.js

Middleware is one of those interesting concepts that once you get it is very, very helpful. I learned this from making the autominify middleware for express.

The concept goes like this:
Express is initialized. Each time you add an app.use call, it appends it to a list of things to try every time someone requests a file. When a file is requested, each of these is called in turn and, if they don’t care about the request, they call a next() function and Express moves onto the next app.use call. If nothing claims the request, a 404 is called.

The syntax is pretty simple, but there’s some useful things I’ve done in autominify that you might want to use, as well.

This is the simplesty example of this I could think of. An inline function only executes if “helloworld” is somewhere in your url. This could be as simple as
http://localhost:3000?helloworld=true
and it would produce “helloworld” as the page.
If you didn’t have helloworld in your url, it would process as normal.

app.use(function(req, res, next){
	if(req.url.indexOf('helloworld') != -1){
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.end('helloworld');
	}
	else
	{
		next();
	}
});

Remember that app.use executes in order, so if something else handles the request before you do, you’ll never see your code work.

If you’re looking to make a module, here’s the basics you might need.

//in app.js
var myModule = require('myModule');
app.use(myModule(true));
//file called myModule.js
module.exports = function (goodbye) {
	var mainText = "hello world";
	if(goodbye)
	{
		mainText = "goodbye world"
	}
 
	return function (req, res, next) {
		if(req.url.indexOf('helloworld') != -1){
			res.writeHead(200, {'Content-Type': 'text/plain'});
			res.end(mainText);
		}
		else
		{
			next();
		}
	}
}

You’ve passed in true as an init param. This would mean that all sessions that are handled with this middleware (any request with helloworld in the url) would receive “goodbye world” as the text on the page.

PHP, Python, GoLang, and Node.js all served by Apache port 80

I dabble in node.js, php, python, and more. Often, these services will produce webservers, and I’d like to try them out in my browser. I also would like to be able to test redirects for things like oauth. In order to get a proper passback from somewhere like Facebook, I need to simulate a full website url without port. It also would be nice to do this without having to shut down one, adjust settings, and restart the other.

The concept:
/etc/hosts or Windows/system32/drivers/hosts will handle incoming request handling to a url

  • Apache handles all requests from port 80
  • Apache uses VirtualHosts to redirect traffic from port 80 to various ports
  • Node/Python/Go/Etc. Will handle requests from specific ports.

An example:
/etc/hosts:

127.0.0.1   local.simplestexplanation.com

This tells your computer that every program that requests data from local.simplestexplanation.com should be forwarded to your computer. This is true for all protocols, http, https, ftp, etc.

httpd.conf:

<VirtualHost *:80>
    ServerName local.simplestexplanation.com
    ProxyPass / http://127.0.0.1:3000/ retry=0
</VirtualHost>

We’ve told apache to create a VirtualHost on port 80. The servername matches the entry in /etc/hosts. The proxypass indicates to where we should forward this request, in this case, to local port 3000. retry=0 tells apache not to cache the results and to always try to serve the page (even if node was down last time)

app.js:

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(3000);

This is a basic node server using port 3000. If we receive a request to http://local.simplestexplanation.com we should see it handled by node.

Similar servers can be set up in Python, GoLang, etc. And as long as they don’t steal port 80 from Apache, they can handle requests as normal. I’ve found this very useful.