Creating your own web server in Node.js
If you’re a Full Stack Software Engineer there’s a pretty good chance you’ve written a HTTP server using Node.js. The core Node.js modules available for creating web servers are fairly low-level, leading to the popularity of open-source projects such as Express and Koa .
I’ve been writing web servers for the Node.js runtime in my professional and personal life for the last four years, so when I found myself with some spare time recently I decided to try and see if I could dive into the lower-level core Node.js modules and make something similar to Express or Koa; after an afternoon’s worth of work I’d created something - Vigilante .
Why the name Vigilante?
I’ve always been pretty terrible when it comes to naming things so I like to use GitHub’s repository name generator.
Starting point
Before starting this project I decided to do some reading about how the core
Node.js module for working with HTTP servers
(http
) works. I came across this
fantastic article
from the Node.js foundation themselves; it’s well worth a read and contained
almost all of the information I needed to write Vigilante.
To begin with I started to build a very simple HTTP server that would respond to all requests with a 200 status code and no response body:
The code is fairly self-explanatory so I won’t spend too much time explaining it, but after this we now have a HTTP web server (running on port 8080) which will send a 200 status code for every request.
Routing
The key thing you may have noticed that is missing from the first example is the
lack of routing; there is nothing different about the way a GET request for
/foo
is handled compared to a POST request for /bar
. That’s a pretty
fundamental requirement when it comes to writing a web server.
Before I looked at approaching routing, I chose to compare the differences
between how Koa and Express approached this problem. I found
this guide
written by Koa themselves which features some nice comparisons of the various
differences between Koa and Express (including how they approach routing).
Essentially, Koa takes a bare-bones approach and instead relies on third-party
libraries to integrate and provide routing functionality
(e.g. koa-router
). Express, on
the other hand, provides routing itself.
For Vigilante I decided to take the Express approach of providing routing without needing any third-party libraries; partly because it was the approach I am most used too, but mainly because it seemed simpler for what it ultimately an afternoon’s worth of side project.
My routing implementation is fairly simple. I introduced the concept of route
handlers where each route handler is an object with three properties: method
,
path
and handle
. The method
and path
are fairly self-explanatory; they
are the HTTP method and path for a specified route. handle
is a function which
will be used to actually finish a request (e.g. by sending a response to a
client).
Middleware
The last piece of functionality I wanted to implement was middleware. Similar to the routing problem I chose to emulate how Express’ middleware works. I do actually prefer how Koa implements middleware (see the “Cascading” section on the docs ) but, similar to my approach the routing, I went for the simpler approach given I was only spending an afternoon on it.
As you can see, my concept of middleware is fairly simple. Middleware is an
array of functions; these functions are ran in order and are provided with the
request object as a single parameter. In the above example I am using middleware
to set a property (message
) on the request object; this can then be read in
the route handler.