📖 Scenario: You are building a simple Express server that logs requests differently based on a log level setting.This helps you see only important logs in production and more details during development.
🎯 Goal: Create a middleware factory function that returns a logging middleware configured with a given log level.Use this middleware in your Express app to log requests accordingly.
📋 What You'll Learn
Create a middleware factory function named createLogger that accepts a level parameter.
Inside the factory, return a middleware function that logs the HTTP method and URL.
If level is 'verbose', also log the request headers.
Use the middleware in an Express app for all routes.
Start the Express server on port 3000.
💡 Why This Matters
🌍 Real World
Middleware factories let you create reusable and configurable middleware for web servers, making your code cleaner and easier to maintain.
💼 Career
Understanding middleware patterns is essential for backend developers working with Express or similar frameworks to build scalable and flexible web applications.
Progress0 / 4 steps
1
Setup Express app
Create an Express app by requiring express and calling express(). Store it in a variable called app.
Express
Hint
Use require('express') to import Express and then call it to create the app.
2
Create middleware factory function
Write a function named createLogger that takes one parameter level and returns a middleware function with parameters req, res, and next.
Express
Hint
The factory returns a middleware function that takes req, res, and next.
3
Add logging logic inside middleware
Inside the middleware returned by createLogger, log the HTTP method and URL using console.log. If level is 'verbose', also log req.headers. Then call next().
Express
Hint
Use template strings to log method and URL. Check if level equals 'verbose' to log headers.
4
Use middleware and start server
Use app.use to add the middleware from createLogger with the argument 'verbose'. Then start the server on port 3000 using app.listen.
Express
Hint
Call app.use with the middleware from createLogger('verbose'). Then call app.listen(3000) to start the server.
Practice
(1/5)
1. What is the main purpose of the middleware factory pattern in Express?
easy
A. To automatically handle errors in middleware
B. To create middleware functions that can be customized with different settings
The middleware factory pattern is used to create middleware functions that accept parameters to customize their behavior.
Step 2: Compare options with the concept
Only To create middleware functions that can be customized with different settings correctly describes creating customizable middleware functions. Other options describe unrelated features.
Final Answer:
To create middleware functions that can be customized with different settings -> Option B
Hint: Middleware factory = function returning middleware with parameters [OK]
Common Mistakes:
Thinking it automatically handles errors
Confusing with routing or caching
Believing it speeds response time directly
2. Which of the following is the correct syntax for a middleware factory function in Express?
easy
A. function logger() { /* middleware code */ }
B. function logger(req, res, next) { return function(level) { /* middleware code */ } }
C. function logger(level) { return function(req, res, next) { /* middleware code */ } }
D. function logger(level, req, res, next) { /* middleware code */ }
Solution
Step 1: Identify middleware factory structure
A middleware factory is a function that takes parameters and returns a middleware function with signature (req, res, next).
Step 2: Match syntax to this pattern
function logger(level) { return function(req, res, next) { /* middleware code */ } } matches this: it takes 'level' and returns a function with (req, res, next). Others do not follow this pattern.
Final Answer:
function logger(level) { return function(req, res, next) { /* middleware code */ } } -> Option C
Quick Check:
Factory returns middleware function = function logger(level) { return function(req, res, next) { /* middleware code */ } } [OK]
Hint: Factory takes params, returns (req, res, next) function [OK]
Common Mistakes:
Placing req, res, next in factory parameters
Not returning a middleware function
Confusing middleware and factory signatures
3. Given the middleware factory below, what will be logged when a request is made?
C. Middleware factory should not return a function
D. Missing parentheses when calling next()
Solution
Step 1: Review middleware function call
Inside middleware, next must be called as a function: next().
Step 2: Identify the error
The code uses 'next;' instead of 'next();', so middleware will not proceed correctly.
Final Answer:
Missing parentheses when calling next() -> Option D
Quick Check:
Call next() with parentheses [OK]
Hint: Always call next() as a function, not just next [OK]
Common Mistakes:
Writing next without parentheses
Confusing status and send methods
Thinking factory should not return a function
5. You want to create a middleware factory that limits requests based on a max count per user. Which approach correctly applies the middleware factory pattern to achieve this?
hard
A. function rateLimiter(maxRequests) {
const counts = new Map();
return function(req, res, next) {
const user = req.user.id;
counts.set(user, (counts.get(user) || 0) + 1);
if(counts.get(user) > maxRequests) {
res.status(429).send('Too many requests');
} else {
next();
}
};
}
B. function rateLimiter(req, res, next, maxRequests) {
// logic here
}
C. function rateLimiter(maxRequests) {
return function(req, res) {
// missing next call
};
}
D. function rateLimiter() {
// no parameters, fixed limit
}
Solution
Step 1: Understand the requirement for customizable limit
The middleware must accept maxRequests as a parameter to customize the limit.
Step 2: Check which option correctly returns middleware with (req, res, next) and uses maxRequests
function rateLimiter(maxRequests) {
const counts = new Map();
return function(req, res, next) {
const user = req.user.id;
counts.set(user, (counts.get(user) || 0) + 1);
if(counts.get(user) > maxRequests) {
res.status(429).send('Too many requests');
} else {
next();
}
};
} correctly implements a factory that returns middleware tracking counts and enforcing maxRequests, calling next() properly.
Final Answer:
function rateLimiter(maxRequests) {
const counts = new Map();
return function(req, res, next) {
const user = req.user.id;
counts.set(user, (counts.get(user) || 0) + 1);
if(counts.get(user) > maxRequests) {
res.status(429).send('Too many requests');
} else {
next();
}
};
} -> Option A
Quick Check:
Factory with param returns middleware calling next() = function rateLimiter(maxRequests) {
const counts = new Map();
return function(req, res, next) {
const user = req.user.id;
counts.set(user, (counts.get(user) || 0) + 1);
if(counts.get(user) > maxRequests) {
res.status(429).send('Too many requests');
} else {
next();
}
};
} [OK]