Express Routing

Summary: in this tutorial, you’ll learn about Express routing which is a process of defining endpoints (URIs) and how to respond when the client requests those endpoints.

Introduction to Express routing

In Express, an endpoint is a URI (or path) and a specific HTTP method (GET, POST, PUT, DELETE, etc.)

For example, the following defines an endpoint:

GET /

In this endpoint, the HTTP method is GET and / is the path. It is known as the home endpoint.

Routing is a process of defining endpoints and how the app should respond to client requests to a particular endpoint.

A route is a section of code that defines how the Express app responds to a client request to a particular endpoint.

In Express, you define a route using a method of the Express app object such as get, post, put, patch, and delete, which corresponds to HTTP methods.

Here’s the syntax for defining a route:

app.method(path, handler);Code language: JavaScript (javascript)

In this syntax:

  • app is an instance of the Express application.
  • method is an HTTP request method in lowercase e.g., get, post, put, patch, and delete.
  • path is the path on the server.
  • handler is a function executed when the route is matched. The route handler has access to the req and res objects, which correspond to HTTP request and response objects.

Basic route examples

The following defines a route for GET requests to the root URL (‘/’):

app.get('/', (req, res) => {
   res.send('Hello World');
});Code language: PHP (php)

Similarly, the following defines a route for the GET request to ‘/about’:

app.get('/about', (req, res) => {
   res.send('About Page');
});Code language: PHP (php)

The following example defines a route for POST requests to ‘/login’:

app.post('/login', (req, res) => {
   res.send('Authenticated');
});Code language: PHP (php)

Express routing examples

Let’s create an Express with a couple of routes.

Create an Express app

Step 1. Open your terminal or command prompt and create a new directory such as express-routing:

mkdir express-routing
cd express-routingCode language: JavaScript (javascript)

Step 2. Run the following npm command to initialize the project:

npm init -yCode language: JavaScript (javascript)

Step 3. Install Express by running the following npm command from the terminal:

npm install expressCode language: JavaScript (javascript)

Step 4. Add the .env file to the project and set the PORT to 3000:

PORT=3000Code language: JavaScript (javascript)

Step 5. Add the following key/value pair to the package.json file to instruct Node.js to use ES modules:

"type": "module"Code language: JavaScript (javascript)

Also, change the scripts section to the following:

  "scripts": {
    "start": "node --watch index.js"
  },Code language: JavaScript (javascript)

This allows you to run the npm start command to execute the index.js file with the --watch flag.

Step 6. Create an index.js file with the following code:

import express from 'express';

const app = express();
const PORT = process.env.PORT || 3000;


app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)

Step 7. Start the server by running the following command from the terminal:

npm startCode language: JavaScript (javascript)

Step 8. Create an api.http file for making requests to routes using REST Client extension in VS Code.

Adding routes

Step 1. Create a new module todos.js module that exports an array of todo items and a function that returns the next todo id:

export const todos = [
  { id: 1, title: 'Learn Node.js', completed: true },
  { id: 2, title: 'Master Express', completed: false },
  { id: 3, title: 'Build an API Server', completed: false },
];

export const nextTodoId = () => {
  // get the next id for the todo
  let maxId = 1;
  todos.forEach((todo) => {
    if (todo.id > maxId) {
      maxId = todo.id;
    }
  });

  return maxId + 1;
};Code language: JavaScript (javascript)

Step 2. Import the todos array and nextTodoId function from the todo.js module into the index.js module:

import { todos, nextTodoId} from './todos.js';Code language: JavaScript (javascript)

Step 3. Define a route for a GET request to the '/api/todos/' endpoint:

import express from 'express';
import { todos, nextTodoId} from './todos.js';

const app = express();

const PORT = process.env.PORT || 3000;

app.get('/api/todos/', (req, res) => {
  res.send(todos);
});

app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)

Step 4. Modify the api.http by adding the HTTP request to the /api/todos endpoint:

# Get all todos items
GET http://localhost:3000/api/todos/Code language: JavaScript (javascript)

When a GET request is made to the /api/todos/ endpoint, the route handler is executed, which responds with the ‘todos’ array as JSON data:

[
  {
    "id": 1,
    "title": "Learn Node.js",
    "completed": true
  },
  {
    "id": 2,
    "title": "Master Express",
    "completed": false
  },
  {
    "id": 3,
    "title": "Build an API Server",
    "completed": false
  }
]Code language: JavaScript (javascript)

Adding a query string to a route

To retrieve a list of completed or incompleted todo items, you can append a query string to the route /api/todos like this:

http://localhost:3000/api/todos/?completed=trueCode language: JavaScript (javascript)

or

http://localhost:3000/api/todos/?completed=falseCode language: JavaScript (javascript)

Everything after the question mark (?) in the URL is called a query string. In our example, the query string is the following:

completed=falseCode language: JavaScript (javascript)

A query string may include one or more parameters, where each parameter is represented by a unique key/value pair separated by an equals sign (=).

To access the query string from the URL in Express, you use the req.query object like this:

req.queryCode language: JavaScript (javascript)

For example:

// ... 

app.get('/api/todos/', (req, res) => {
  console.log(req.query);
});

// ...Code language: JavaScript (javascript)

If you make a GET request to the endpoint http://localhost:3000/api/todos/?completed=false, you’ll see the following query object in the console:

{ completed: 'false' }Code language: JavaScript (javascript)

To access the completed parameter in the query string, you can use the following:

app.get('/api/todos/', (req, res) => {
  console.log(req.query.completed);
});Code language: JavaScript (javascript)

The following modifies the /api/todos/ endpoint to return the incompleted/completed todo items if the completed query string is available:

app.get('/api/todos/', (req, res) => {
  if (req?.query?.completed) {
    const isCompleted = req.query.completed === 'true';
    const filteredTodos = todos.filter(
      (todo) => todo.completed === isCompleted
    );
    res.send(filteredTodos);
  }

  res.send(todos);
});Code language: JavaScript (javascript)

Here’s the updated version of the api.http file:

# Get all todos items
GET http://localhost:3000/api/todos/

### 

# Get incompleted todo items:
GET http://localhost:3000/api/todos/?completed=false

### 

# Get completed todo items:
GET http://localhost:3000/api/todos/?completed=trueCode language: JavaScript (javascript)

Handling route parameters

A route segment is a named URL segment used to capture the value specified at its position in the URL. For example:

http://localhost:3000/api/todos/1Code language: JavaScript (javascript)

In this URL, 1 is a route parameter representing the todo id.

In Express, you can set up the route with id like this:

/api/todo/:idCode language: JavaScript (javascript)

To access route parameters, you use the req.params object:

req.paramsCode language: JavaScript (javascript)

In the route /api/todo/:id, the id is a key of the req.params object. So you can access it using the following:

req.params.idCode language: JavaScript (javascript)

Note that the values of route parameters are always strings. Therefore, you need to convert them into the values of desired types.

The following defines a route that returns a todo item by an id:

app.get('/api/todos/:id', (req, res) => {
  const { id } = req.params;

  const todoId = parseInt(id);
  if (isNaN(todoId)) {
    res.status(400).send(`Invalid id ${id}`);
  }

  const todo = todos.find((todo) => todo.id === todoId);
  if (todo) res.status(200).send(todo);

  res.status(404).send(`Todo with id ${id} not found`);
});Code language: JavaScript (javascript)

How it works.

First, get the id from the req.params object by destructing the object:

const { id } = req.params;Code language: JavaScript (javascript)

Second, convert the id value to an integer. If the id is not a number, respond with HTTP status code 400 with an error message:

const todoId = parseInt(id);
if (isNaN(todoId)) {
   res.status(400).send(`Invalid id ${id}`);
}Code language: JavaScript (javascript)

Third, find the todo with the id and return it as JSON to the client:

const todo = todos.find((todo) => todo.id === id);
if (todo) res.send(todo);Code language: JavaScript (javascript)

Finally, return the HTTP status code 404 if the todo with the id is not found:

res.status(404).send(`Todo with id ${id} not found`);Code language: JavaScript (javascript)

Put it all together

The following shows the completed index.js module:

import express from 'express';
import { todos, nextTodoId } from './todos.js';

const app = express();

const PORT = process.env.PORT || 3000;

app.get('/api/todos/', (req, res) => {
  if (req?.query?.completed) {
    const isCompleted = req.query.completed === 'true';
    const filteredTodos = todos.filter(
      (todo) => todo.completed === isCompleted
    );
    res.send(filteredTodos);
  }

  res.send(todos);
});

app.get('/api/todos/:id', (req, res) => {
  const { id } = req.params;

  const todoId = parseInt(id);
  if (isNaN(todoId)) {
    res.status(400).send(`Invalid id ${id}`);
  }

  const todo = todos.find((todo) => todo.id === todoId);
  if (todo) res.status(200).send(todo);

  res.status(404).send(`Todo with id ${id} not found`);
});

app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});
Code language: JavaScript (javascript)

Download the Express Routing example source code

Summary

  • An endpoint is a combination of a URI and HTTP method.
  • A route is a section of code that defines how the Express app responds to a client request to a particular endpoint.
  • Use methods of Express app object to define routes.
Was this tutorial helpful ?