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 /todos
In this endpoint, The path is /todos
and the HTTP method is GET
.
The following endpoint creates a new todo item:
POST /todos
The 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:
app
is an instance of theExpress
application.method
is an HTTP request method in lowercase e.g.,get
,post
,put
,patch
, anddelete
.path
is the path on the server.handler
is a function executed when the route is matched. The route handler has access to thereq
andres
objects, 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-routing
Code language: JavaScript (javascript)
Step 2. Run the following npm
command to initialize the project:
npm init -y
Code 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 express
Code language: JavaScript (javascript)
Step 4. Add the .env
file to the project and set the PORT
to 3000
:
PORT=3000
Code 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 start
Code 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=true
Code language: JavaScript (javascript)
or
http://localhost:3000/api/todos/?completed=false
Code 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=false
Code 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.query
Code 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=true
Code 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/1
Code 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/:id
Code language: JavaScript (javascript)
To access route parameters, you use the req.params
object:
req.params
Code 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.id
Code 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.