Summary: in this tutorial, you’ll learn about Express routing, a process of defining endpoints (URIs) and responding when the client requests those endpoints.
Introduction to Express Routing
An endpoint is a specific URL (Uniform Resource Locator) or path and an HTTP method (GET, POST, PUT, …)
Typically, an endpoint represents a specific resource or function which a client can perform such as fetching data, modifying data, and deleting records.
For example, the following endpoint retrieves a list of todos:
GET /todosIn this endpoint, The path is /todos and the HTTP method is GET.
The following endpoint creates a new todo item:
POST /todosThe path is also /todos but the HTTP is POST.
In Express, routing is about setting up endpoints and defining how the app should respond when a client requests to those endpoints.
A route defines how your app handles requests to an endpoint. To define a route, you use a method of the Express object such as get, post, put, patch, and delete and a
Here’s the syntax for defining a route:
app.method(path, handler);Code language: JavaScript (javascript)In this syntax:
appis an instance of theExpressapplication.methodis an HTTP request method in lowercase e.g.,get,post,put,patch, anddelete.pathis the path on the server.handleris a function executed when the route is matched. The route handler has access to thereqandresobjects, which correspond to HTTP request and response objects.
Basic route examples
The following defines a route for the 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 app with a couple of routes.
Creating 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)This will create a package.json file that includes configurations, scripts, and dependencies.
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 --env-file=.env 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 and load the .env file.
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 an 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 to 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)Putting 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 refers to a specific URL (or path) and an HTTP method that a client can use to access a resource or perform an operation function.
- A route defines how the app responds to a particular endpoint.
- Use methods of Express app object to define routes.