Introductions
Express middleware is a function that runs between the incoming request and the final response. Middleware can log requests, check users, validate data, modify requests, handle errors, and perform many other tasks. In this chapter, you will practice Express middleware through 10 solved questions, starting with basic middleware and gradually moving to multiple middleware, route-specific middleware, built-in middleware, custom middleware, authentication checks, validation, and error-handling middleware. Node.js Express Middleware practice questions with solutions help to understand the concepts.
Question 1: How do you create basic middleware in Express.js?
Problem
Create middleware that prints a message whenever a request reaches the Express server.
Solution
const express = require("express");
const app = express();
app.use((req, res, next) => {
console.log("Middleware executed.");
next();
});
app.get("/", (req, res) => {
res.send("Home Page");
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Run the Application
node index.js
Open:
http://localhost:3000
Browser Output
Home Page
Console Output
Middleware executed.
Step-by-Step Explanation
This is middleware:
(req, res, next) => {
console.log("Middleware executed.");
next();
}
The three important parameters are:
req
res
next
req contains information about the incoming request.
res is used to send a response.
next() tells Express to continue to the next middleware or route handler.
The middleware is registered using:
app.use(...)
Request Flow
Browser
↓
Middleware
↓
next()
↓
Route
↓
Response
Important Point
If middleware does not send a response, it normally needs to call next() so the request can continue.
Question 2: How do you create middleware that logs HTTP method and URL?
Problem
Create a logging middleware that displays the HTTP method and requested URL in the terminal.
Solution
const express = require("express");
const app = express();
app.use((req, res, next) => {
console.log(
`Method: ${req.method}`
);
console.log(
`URL: ${req.url}`
);
next();
});
app.get("/", (req, res) => {
res.send("Home Page");
});
app.get("/about", (req, res) => {
res.send("About Page");
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Test
Open:
http://localhost:3000/
Console:
Method: GET
URL: /
Now open:
http://localhost:3000/about
Console:
Method: GET
URL: /about
Step-by-Step Explanation
The HTTP method is available through:
req.method
The requested URL is available through:
req.url
The middleware runs before both routes because:
app.use(...)
was placed before the routes.
Question 3: How do you use multiple middleware functions?
Problem
Create two middleware functions. The first should print a message, and the second should print another message before sending the response.
Solution
const express = require("express");
const app = express();
const firstMiddleware = (req, res, next) => {
console.log("First middleware");
next();
};
const secondMiddleware = (req, res, next) => {
console.log("Second middleware");
next();
};
app.get(
"/",
firstMiddleware,
secondMiddleware,
(req, res) => {
res.send("Home Page");
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Console Output
When you visit /:
First middleware
Second middleware
Step-by-Step Explanation
The request enters:
firstMiddleware
Then:
next();
passes control to:
secondMiddleware
Then its:
next();
passes control to the final route handler.
Request Flow
Request
↓
First Middleware
↓
next()
↓
Second Middleware
↓
next()
↓
Route Handler
↓
Response
Important Point
Middleware functions execute in the order in which they are registered.
Question 4: How do you create route-specific middleware?
Problem
Create an authentication middleware that runs only for the /dashboard route.
Solution
const express = require("express");
const app = express();
const checkLogin = (req, res, next) => {
const loggedIn = true;
if (!loggedIn) {
return res.status(401).send(
"Please login first."
);
}
next();
};
app.get("/home", (req, res) => {
res.send("Home Page");
});
app.get(
"/dashboard",
checkLogin,
(req, res) => {
res.send("Welcome to your Dashboard.");
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Test
Open:
http://localhost:3000/dashboard
Output:
Welcome to your Dashboard.
Step-by-Step Explanation
The middleware is:
const checkLogin = (req, res, next) => {
The login status is temporarily represented by:
const loggedIn = true;
If the user is not logged in:
if (!loggedIn) {
the server sends:
return res.status(401).send(
"Please login first."
);
Otherwise:
next();
allows the request to reach the dashboard.
Question 5: How do you use built-in JSON middleware?
Problem
Create a POST API that receives JSON data from the client.
Solution
const express = require("express");
const app = express();
app.use(express.json());
app.post("/students", (req, res) => {
const name = req.body.name;
const course = req.body.course;
res.json({
message: "Student received.",
name: name,
course: course
});
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Send This JSON
{
"name": "Rahul",
"course": "Node.js"
}
Response
{
"message": "Student received.",
"name": "Rahul",
"course": "Node.js"
}
Step-by-Step Explanation
This line enables JSON parsing:
app.use(express.json());
The incoming JSON can then be accessed through:
req.body
For example:
req.body.name
gets the name.
And:
req.body.course
gets the course.
Question 6: How do you create validation middleware?
Problem
Create middleware that checks whether name and email are present before creating a student.
Solution
const express = require("express");
const app = express();
app.use(express.json());
const validateStudent = (req, res, next) => {
const {
name,
email
} = req.body;
if (!name || !email) {
return res.status(400).json({
success: false,
message: "Name and email are required."
});
}
next();
};
app.post(
"/students",
validateStudent,
(req, res) => {
res.status(201).json({
success: true,
message: "Student created.",
student: req.body
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Valid Request
{
"name": "Aman",
"email": "aman@example.com"
}
Response
{
"success": true,
"message": "Student created.",
"student": {
"name": "Aman",
"email": "aman@example.com"
}
}
Invalid Request
{
"name": "Aman"
}
Response
{
"success": false,
"message": "Name and email are required."
}
Step-by-Step Explanation
The middleware extracts:
const {
name,
email
} = req.body;
Then checks:
if (!name || !email)
If something is missing, the middleware sends a response and stops.
If everything is present:
next();
allows the request to continue.
Question 7: How do you modify the request object using middleware?
Problem
Create middleware that adds the current user’s name to the request object before the route runs.
Solution
const express = require("express");
const app = express();
const addUser = (req, res, next) => {
req.user = {
name: "Rahul",
role: "student"
};
next();
};
app.get(
"/profile",
addUser,
(req, res) => {
res.json({
message: "User profile",
user: req.user
});
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Output
{
"message": "User profile",
"user": {
"name": "Rahul",
"role": "student"
}
}
Step-by-Step Explanation
Middleware adds a new property:
req.user = {
name: "Rahul",
role: "student"
};
Then:
next();
passes the modified request to the route.
The route can now access:
req.user
Request Flow
Request
↓
addUser Middleware
↓
req.user added
↓
next()
↓
/profile Route
↓
Response
Important Point
Adding information to req is a common pattern when middleware needs to pass data to later middleware or route handlers.
Question 8: How do you create role-based middleware?
Problem
Allow only admin users to access an admin page.
Solution
const express = require("express");
const app = express();
const checkAdmin = (req, res, next) => {
const user = {
name: "Rahul",
role: "student"
};
if (user.role !== "admin") {
return res.status(403).json({
success: false,
message: "Access denied."
});
}
next();
};
app.get(
"/admin",
checkAdmin,
(req, res) => {
res.send("Welcome Admin.");
}
);
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Output
Because the user’s role is:
student
the server returns:
{
"success": false,
"message": "Access denied."
}
with status:
403 Forbidden
Step-by-Step Explanation
The middleware checks:
if (user.role !== "admin")
If the role is not admin, the request is stopped:
return res.status(403).json({
success: false,
message: "Access denied."
});
If the role is admin, the middleware would call:
next();
Question 9: How do you create error-handling middleware?
Problem
Create an Express application that catches an error and sends a JSON response.
Solution
const express = require("express");
const app = express();
app.get("/error", (req, res, next) => {
const error = new Error(
"Something went wrong."
);
next(error);
});
app.use((error, req, res, next) => {
console.error(error.message);
res.status(500).json({
success: false,
message: error.message
});
});
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Test
Open:
http://localhost:3000/error
Output
{
"success": false,
"message": "Something went wrong."
}
Step-by-Step Explanation
The route creates an error:
const error = new Error(
"Something went wrong."
);
Then passes it to Express:
next(error);
Because next() receives an error, Express looks for error-handling middleware.
The error middleware has four parameters:
(error, req, res, next)
This is important.
It sends:
res.status(500).json({
success: false,
message: error.message
});
Question 10: How do you combine multiple Express middleware types in one application?
Problem
Create a small Express application containing:
- Global logging middleware
- JSON middleware
- User middleware
- Validation middleware
- Route-specific middleware
- Error-handling middleware
- A student API
Solution
const express = require("express");
const app = express();
// 1. Built-in JSON middleware
app.use(express.json());
// 2. Global logging middleware
app.use((req, res, next) => {
console.log(
`${req.method} ${req.url}`
);
next();
});
// 3. User middleware
const addUser = (req, res, next) => {
req.user = {
name: "Rahul",
role: "student"
};
next();
};
// 4. Validation middleware
const validateStudent = (req, res, next) => {
const {
name,
course
} = req.body;
if (!name || !course) {
return res.status(400).json({
success: false,
message: "Name and course are required."
});
}
next();
};
// 5. Student route
app.post(
"/students",
addUser,
validateStudent,
(req, res) => {
res.status(201).json({
success: true,
message: "Student created successfully.",
createdBy: req.user.name,
student: {
name: req.body.name,
course: req.body.course
}
});
}
);
// 6. Error route
app.get("/error", (req, res, next) => {
next(
new Error("Demo server error.")
);
});
// 7. 404 middleware
app.use((req, res, next) => {
const error = new Error(
"Route not found."
);
error.statusCode = 404;
next(error);
});
// 8. Error-handling middleware
app.use(
(error, req, res, next) => {
console.error(
error.message
);
const statusCode =
error.statusCode || 500;
res.status(statusCode).json({
success: false,
message: error.message
});
}
);
// Start server
app.listen(3000, () => {
console.log(
"Server running on http://localhost:3000"
);
});
Test the Application
Test 1: Create Student
Send:
POST /students
with:
{
"name": "Aman",
"course": "Node.js"
}
Response
{
"success": true,
"message": "Student created successfully.",
"createdBy": "Rahul",
"student": {
"name": "Aman",
"course": "Node.js"
}
}
What Happened?
The request passed through:
express.json()
↓
Logging Middleware
↓
addUser
↓
validateStudent
↓
POST /students
↓
Response
Test 2: Send Invalid Data
Send:
{
"name": "Aman"
}
The validation middleware detects that course is missing.
Response:
{
"success": false,
"message": "Name and course are required."
}
Test 3: Open an Unknown Route
Visit:
http://localhost:3000/hello
Response:
{
"success": false,
"message": "Route not found."
}
Test 4: Trigger an Error
Visit:
http://localhost:3000/error
Response:
{
"success": false,
"message": "Demo server error."
}
Step-by-Step Middleware Flow
The complete request flow looks like this:
Client Request
↓
express.json()
↓
Logging Middleware
↓
Route-Specific Middleware
↓
Validation Middleware
↓
Route Handler
↓
Response
If something goes wrong:
Error
↓
Error-Handling Middleware
↓
Error Response
Key Takeaways
- Middleware is a function that runs during the Express request-response cycle.
- Middleware can execute before a route handler.
- Middleware normally receives
req,res, andnext. reqcontains information about the incoming request.resis used to send a response.next()passes control to the next middleware or route handler.app.use()is commonly used to register middleware.- Middleware executes in the order in which it is registered.
- Multiple middleware functions can be used for one route.
- Middleware can be global or route-specific.
- Global middleware can affect many or all routes.
- Route-specific middleware runs only for selected routes.
express.json()is built-in middleware for parsing JSON request bodies.- Middleware can validate incoming data.
- Middleware can add information to the
reqobject. - Authentication checks can be implemented as middleware.
- Authorization and role checks can be implemented as middleware.
- Middleware can stop a request by sending a response.
- Middleware can pass an error to Express using
next(error). - Error-handling middleware has four parameters:
error,req,res, andnext. - A 404 handler can be implemented using middleware.
- Middleware helps keep application logic organized.
- Validation middleware can prevent invalid data from reaching the main route.
- Logging middleware can help monitor incoming requests.
- Middleware is a core concept used in Express-based REST APIs.
FAQs
1. What is middleware in Express.js?
Middleware is a function that runs between the incoming request and the final response.
A basic middleware function looks like:
app.use((req, res, next) => {
console.log("Middleware executed.");
next();
});
It can perform tasks such as logging, authentication, validation, and request processing.
2. What does next() do in Express middleware?
next() tells Express to continue to the next middleware or route handler.
Example:
app.use((req, res, next) => {
console.log("First middleware");
next();
});
Without next(), the request may stop if the middleware does not send a response.
3. What is the difference between app.use() and route-specific middleware?
app.use() is commonly used to register middleware that can run for multiple routes.
Example:
app.use(loggingMiddleware);
Route-specific middleware is attached directly to a route:
app.get(
"/admin",
checkAdmin,
(req, res) => {
res.send("Admin Page");
}
);
The second example runs checkAdmin only for the /admin route.
4. What is express.json() in Express.js?
express.json() is built-in Express middleware that parses incoming JSON request bodies.
Example:
app.use(express.json());
After enabling it, JSON data can be accessed through:
req.body
5. Can middleware modify req and res?
Yes. Middleware can add or modify properties on the request and response objects.
For example:
req.user = {
name: "Rahul",
role: "student"
};
A later route can access:
req.user
This pattern is commonly used to pass information from middleware to route handlers.
6. What is error-handling middleware in Express.js?
Error-handling middleware handles errors that occur during request processing.
It has four parameters:
(error, req, res, next)
Example:
app.use((error, req, res, next) => {
res.status(500).json({
message: error.message
});
});
Express identifies it as error-handling middleware because of the four-parameter function signature.
7. Can multiple middleware functions be used on one Express route?
Yes. You can use multiple middleware functions on the same route.
Example:
app.post(
"/students",
authenticate,
validateStudent,
createStudent
);
The request moves through the middleware functions in order. Each middleware normally calls next() when it wants the request to continue.
Written by Shubhranshu Shekhar, who has trained 20000+ students in coding.
