Express.js Cheat Sheet

Express.js helps abstract the complexities of web services and its Router allows us to modularize our endpoints. This cheat sheet demonstrates how to use Express’s Router for basic RESTful request handling. This is not intended to be a deep dive into writing web services but instead something that can be referenced when learning Express or getting started on a new project. For more in depth study check out the official Express documentation.

Structure

We will be working with two files: server.js and users.service.js. By modularizing our web service with express’s Router we are able to maintain a fairly basic server.js and break down the logic of our api into more manageable modules.

server.js

//Packages
var express = require('express');
var app = express();
var router = express.Router();

//Require the module for our endpoint
var users = require('./routes/users.service');

//Set up the '/users' web service endpoint
app.use('/users', users);

//Set the server port value
app.set('port', 1776);

//Start listening on the configured port
app.listen(app.get('port'), function() {
 console.log('Express server listening on port ' + app.get('port'));
});

You might notice an external package in the users service named http-status-codes. This package is not required but I find it useful to have named HTTP status codes. A list of HTTP status codes and their descriptions can be found on Wikipedia. At this point we’re ready to add routes to the user service.

users.service.js

//Packages
var express = require('express');
var router = express.Router();
var HttpStatus = require('http-status-codes');

//Your endpoints will be configured here

//Makes these configurations available when imported
module.exports = router;

 

GET Request

The GET HTTP request method should be used for retrieving data from your service. Below is the most basic GET endpoint you can write. In this example I’m using the HttpStatus package to send back an OK HTTP status code of 200. In addition to the status code we also send a response body which in this example is the string value Request received. Remember that in our server.js we described the users service as having the endpoint /users. This means that in order to use the endpoint below a request would need to be made to http://localhost:1776/users/.

users.service.js

//Your endpoints will be configured here
router.get('/', function(req, res){
 res.status(HttpStatus.OK).send('Request received.');
});

As opposed to other HTTP request methods, GET endpoints should only accept request parameters through the path. In practice, a GET request with input parameters will look something like http://localhost:1776/users/kevinkulp. With just a couple minor changes we can support path parameters in our service.

users.service.js

//Your endpoints will be configured here
router.get('/:user_id', function(req, res){
 var user_id = req.params.user_id;
 res.status(HttpStatus.OK).send('Request received for ' + user_id);
});

I want to point out that it is completely legitimate to support both of the endpoints described above: /users and /users/:user_id where each endpoint performs different logic.

 

DELETE Request

There are a number of other HTTP methods but I’m going to demonstrate one more, DELETE. Handling another HTTP method is as easy as changing the route function used. Unlike GET methods, DELETE endpoints should accept a request body.

users.service.js

//Your endpoints will be configured here
router.delete('/', function(req, res){
 var user_id = req.body.user_id;

 res.status(HttpStatus.ACCEPTED).send(user_id);
});

 

Input Validation

In addition to modularizing our web service, another benefit of using Express’s Router is that it allows us to perform validation on input parameters that are used by multiple endpoints. This can also be useful for sanitizing and decoding user input.

users.service.js

//Perform validations on input
router.param('user_id', function(req, res, next, user_id) {
 console.log('Performing validations on ' + user_id);

 //We can decode the input and update
 req.user_id = decodeURI(user_id).trim();

 console.log('Validated '+ user_id);

 //Allow the request to continue
 next();
});

 

Catch All

There are many reasons you might want a catch-all whether it be to perform logging or to authenticate the user. Depending on the location of the catch-all you can regulate which endpoints require authorization. Another way we can control the endpoints that trigger our catch-all is by updating the path used below from * to something like /admin/*.

//Catch all
router.all('*', function(req, res, next){
 console.log('Performing authorization');

 //Authorize and set value
 var authorized = true;

 if(authorized === false)
  res.status(HttpStatus.UNAUTHORIZED).send(HttpStatus.getStatusText(HttpStatus.UNAUTHORIZED));
 else
  next();
});