DEV Community

Mario
Mario

Posted on • Originally published at mariokandut.com on

Routing in Express.js explained

Express reduces complexity and makes developing and maintaining applications much easier than the built-in Node.js tools. Routing is one of three big concepts in the Express framework. Read more about Express.js in the Introduction to Express.js.

This article is part of a large series about Express.js. You can find all articles here - Express Framework.

Routing in Express

Routing refers to how an application responds to a client request to a particular endpoint, which is a URI (or a path) and a specific HTTP request method (GET, POST, etc.). Each route can have one or more handler functions, which are executed when the route is matched.

A Route definition takes the following structure: app.METHOD(PATH, HANDLER)

  • app is an instance of express.
  • METHOD is an HTTP request method, in lowercase.
  • PATH is a path on the server.
  • HANDLER is the function executed when the route is matched.

Let's look at an example of a route /home that is defined for a GET request.

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

// GET method route
app.get('/home', (req, res) => {
  res.send('OK');
});
Enter fullscreen mode Exit fullscreen mode

In the above example:

  • app is an instance of Express
  • app.get is the HTTP request method
  • /home is the route
  • (req, res) => {} is the handler function, which runs in response to a matching request.

Route methods

A route method is derived from one of the HTTP methods, and is attached to an instance of the express class. There is a method for every HTTP verb, most commonly used below. For a full list see MDN.

  • GET .get()
  • POST .post()
  • PUT .put()
  • DELETE .delete()
  • PATCH .patch()

Route method .all()

There is a special routing method app.all(). It is used to load middleware functions at a path for all HTTP requests.

app.all('/secret', (req, res, next) => {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});
Enter fullscreen mode Exit fullscreen mode

Route paths

Route paths with a request method define the endpoints at which requests can be made. They can be string, string patterns or regular expressions. Query strings are not part of the route path.

The characters ?, +, *, and () are subsets of their regular expression counterparts. The hyphen (-), and the dot (.) are interpreted literally by string-based paths.

Express uses path-to-regexp for matching the route paths, there are many possibilities, but also limitations in choosing routes. For a full list refer to the documentation of path-to-regexp.

Here are a few examples for routes:

This route path will match requests made to /.

app.get('/', (req, res) => {
  res.send('root');
});
Enter fullscreen mode Exit fullscreen mode

This route path will match requests made to /home.

app.get('/home', (req, res) => {
  res.send('home');
});
Enter fullscreen mode Exit fullscreen mode

This route path will match requests made to /info.text.

app.get('/info.text', (req, res) => {
  res.send('info.text');
});
Enter fullscreen mode Exit fullscreen mode

This route path will match requests made to /acd and /abcd.

app.get('/ab?cd', (req, res) => {
  res.send('ab?cd');
});
Enter fullscreen mode Exit fullscreen mode

This route path will match requests made to abcd, abbcd, abbbcd, etc.

app.get('/ab+cd', (req, res) => {
  res.send('ab+cd');
});
Enter fullscreen mode Exit fullscreen mode

This route path will match requests made to abcd, abxcd, abANYRANDOMSTRINGcd, etc.

app.get('/ab*cd', (req, res) => {
  res.send('ab*cd');
});
Enter fullscreen mode Exit fullscreen mode

Since regular expressions are possible as route paths., this route path will match requests containing an a anywhere.

app.get('/a/', (req, res) => {
  res.send('/a/');
});
Enter fullscreen mode Exit fullscreen mode

Express 4.x treats the * differently, see here. This behaviour is fixed since Express 5.x.

Route parameters

A Route can accept dynamic values within a path, so called route parameters. Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter as their key.

For example a route path /users/:userId/books/:bookId would require a request URL to be something like http://localhost:3000/users/34/books/8989, and the captured route parameters would be populated in req.params like this { "userId": "34", "bookId": "8989" }.

To define a route parameter just specify the route parameters in the path.

app.get(`/users/:userId/books/:bookId`, (req, res) => {
  console.log(req.params);
});
Enter fullscreen mode Exit fullscreen mode

Route handlers

Route handlers are callback functions or arrays of functions, which basically handle requests. Multiple callback functions can be provided to handle a request and behave like a middleware. The only exception is that these callbacks can call next() to bypass the next and remaining route callbacks. Route handlers can be in the form of a function, an array of functions, or a combination of both.

The request and response are often shortened to req and res, and stand for the request which was received by the server, and the response which will eventually be send back.

These are based on built-in objects in Node.js, the ClientRequest and ServerResponse. There will be a dedicated Express routing blog post in the future.

A single HTTP transaction can be roughly described by the Request and Response cycle.

  • A client sends a request to the server.
  • The server receives the request, reads the data (request headers, URL path, HTTP method, query parameters, cookies, data or payload, etc.).
  • The server sends a response back to the client. It includes status code, headers, content-encoding, any data being returned.
  • Once the response has been sent back, the HTTP transaction is completed.

Augmenting the req and res objects is a big part of how Express enhances functionality, while still maintaining control over how requests and responses are handled.

A single callback function can handle a route like this:

app.get('/home', (req, res) => {
  res.send('home');
});
Enter fullscreen mode Exit fullscreen mode

Below an array of functions example:

const cb0 = function(req, res, next) {
  console.log('CB0');
  next();
};

const cb1 = function(req, res, next) {
  console.log('CB1');
  next();
};

app.get('/c', [cb0, cb1]);
Enter fullscreen mode Exit fullscreen mode

Response methods

The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.

  • res.download() Prompt a file to be downloaded.
  • res.end() End the response process.
  • res.json() Send a JSON response.
  • res.jsonp() Send a JSON response with JSONP support.
  • res.redirect() Redirect a request.
  • res.render() Render a view template.
  • res.send() Send a response of various types.
  • res.sendFile() Send a file as an octet stream.
  • res.sendStatus() Set the response status code and send its string representation as the response body.

Chainable Routes with app.route()

With app.route() you can chain route handlers for a route path. Creating modular routes is helpful, because it is reducing redundancy and typos.

Let's have a look at an example of chained route handlers:

app
  .route('/book')
  .get(function(req, res) {
    res.send('Get a random book');
  })
  .post(function(req, res) {
    res.send('Add a book');
  })
  .put(function(req, res) {
    res.send('Update the book');
  });
Enter fullscreen mode Exit fullscreen mode

TL;DR

  • Route paths, in combination with a request method, define the endpoints at which requests can be made. A Route definition takes the following structure: app.METHOD(PATH, HANDLER)
  • Route handlers are callback functions or arrays of functions.
  • For every HTTP verb there is a route method.
  • The special routing method app.all() is used to load middleware functions at a path for all HTTP requests.
  • Route paths can be strings, string patterns or REGEXP.
  • Routes can be chained with app.route()

Thanks for reading and if you have any questions , use the comment function or send me a message @mariokandut.

If you want to know more about Express, have a look at these Express Tutorials.

References (and Big thanks):

HeyNode,ExpressJS,Express - Routing,Express - Basic Routing,path-to-regexp

Top comments (1)

Collapse
 
projektorius96 profile image
Lukas Gaucas

Love your series , Mario !