Introduction to Express' Router

Oct 17, 2019

Routing in Express means mapping an HTTP request to the appropriate request handler. In Express, a request handler is a callback function with the following signature:

function requestHandler(req, res) {}

For example, if you receive an HTTP GET request for /route1, Express should call the request handler for GET /route1 and not call the request handler for GET /route2. Here's how you can define a request handler for GET /route1:

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

// When `app` receives a GET request to `/route1`, Express calls
// the `requestHandler()` function.
app.get('/route1', function requestHandler(req, res) {
  res.send('Hello from route1');
});

// Listen for requests on port 3000
app.listen(3000);

Testing with Axios

The easiest way to see your Express app in action is using Axios - no need to remember CURL flags. Here's a simple script that starts an Express server and makes an HTTP request to that server using Axios and async/await.

const app = require('express')();
app.get('/route1', (req, res) => res.send('Hello, World!'));
// `app.listen()` returns a promise. Once this promise
// resolves, that means Express is ready to handle requests.
const server = await app.listen(3000);

const axios = require('axios');
const res = await axios.get('http://localhost:3000/route1');
res.data; // 'Hello, World!'

Other HTTP Request Methods

The app.get() function defines a request handler specifically for an HTTP GET request. However, there are several HTTP request methods in addition to GET:

Express has a separate function for each of these request methods:

Most apps just use app.get(), app.post(), app.put(), and app.delete(). However, app.options() is useful for CORS. Here's how you can define a POST handler:

app.post('/route1', function(req, res) {
  res.send('Hello from POST /route1');
});

The app.all() function lets you define a route handler for all HTTP methods:

// Express will call `routeHandler()` for any request to
// `/route1`, regardless of the request method. For example,
// `GET /route1` and `POST /route1` both trigger `routeHandler`.
app.all('/route1', function routeHandler(req, res) {});

Wildcards and Route Parameters

Express routing supports a subset of regular expressions, including wildcards. For example, the below is how you define a request handler for all URIs:

// Express will call `requestHandler()` for **every** GET request.
app.get('*', function requestHandler(req, res) {});

The : character is how you define a route parameter in Express. A route parameter is a named section of the URL - Express captures the value in the named section and stores it in the req.params property.

// Express stores whatever string comes after `/user/` in
// `req.params.id`
app.get('/user/:id', (req, res) => res.json({ id: req.params.id }));

await app.listen(3000);

let res = await axios.get('http://localhost:3000/user/test1');
res.data.id; // 'test1'

res = await axios.get('http://localhost:3000/user/test2');
res.data.id; // 'test2'

You can also define multiple route parameters. Route parameters are delimited by /.

// `GET /flight/MIA/JFK` means `req.params` is equal to
// `{ from: 'MIA', to: 'JFK' }`
app.get('/flight/:from/:to', (req, res) => res.json(req.params));

Subrouters

The express.Router() function creates a subrouter. A subrouter is an Express middleware that behaves like a mini Express app. It has the same get(), post(), all(), etc. methods that an Express app does for defining route handlers.

Routers are commonly used as Express sub-apps. For example, you may have a separate router for REST API requests and another router for custom views.

// Set up an API sub-app...
const api = express.Router();

api.get('/users', (req, res) => { res.json({ users: [] }); });

// And a views sub-app...
const views = express.Router();
const fs = require('fs');
const usersPage = fs.readFileSync('./views/users.html', 'utf8');

views.get('/users', (req, res) => res.send(usersPage));

// And add them to a top-level app
const app = express();

// Handles `GET /api/users`
app.use('/api', api);
// Handles `GET /views/users`
app.use('/views', views);

Want to become your team's Express expert? There's no better way to really grok a framework than to write your own clone from scratch. In 15 concise pages, this tutorial walks you through how to write a simplified clone of Express called Espresso. Get your copy!

Espresso supports:
  • Route handlers, like `app.get()` and `app.post()`
  • Express-compatible middleware, like `app.use(require('cors')())`
  • Express 4.0 style subrouters
As a bonus, Espresso also supports async functions, unlike Express.

Get the tutorial and master Express today!

Did you find this tutorial useful? Say thanks by starring our repo on GitHub!

More Express Tutorials