- Express.js Basics
- Express.js HOME
- Express.js Introduction
- Express.js Installation
- Express.js Basic App
- Express.js Routing
- Basics Routing
- Route Parameters
- Handling Query Strings
- Router Middleware
- Middleware
- What is Middleware?
- Application-Level Middleware
- Router-Level Middleware
- Built-In Middleware
- Error-Handling Middleware
- Third-Party Middleware
- Express.js HTTP
- Handling GET Requests
- Handling POST Requests
- Handling PUT Requests
- Handling DELETE Requests
- Templating Engines
- Using Templating Engines
- Setting Up EJS
- Setting Up Handlebars
- Setting Up Pug
- Request/Response
- Request Object
- Response Object
- Handling JSON Data
- Handling Form Data
- Static Files
- Serving Static Files
- Setting Up Static Folders
- Managing Assets
- Express.js Advanced
- Middleware Stack
- CORS in Express.js
- JWT Authentication
- Session Handling
- File Uploads
- Error Handling
- Databases
- Express.js with MongoDB
- MongoDB CRUD Operations
- Express.js with MySQL
- MySQL CRUD Operations
- Deployment
- Deploying Express.js Apps to Heroku
- Deploying Express.js Apps to AWS
- Deploying Express.js Apps to Vercel
Express.js Third-Party Middleware
In the world of Express.js, the core framework is intentionally "unopinionated" and minimalist. This means it doesn't come with everything built-in. Instead, it relies on third-party middleware—external packages maintained by the community—to add essential features. These tools act as "plugins" that sit between the incoming request and your final route handler, performing tasks like security, logging, and data parsing.
Key Features of Third-Party Middleware
- Extends Functionality: It adds complex features (like OAuth login or file uploads) that would take weeks to code from scratch.
- Easy to Integrate: Most middleware follows a standard pattern: install via npm, require it, and then use
app.use(). - Community Audited: Popular middleware like
helmetorcorsis used by millions, meaning bugs and security flaws are caught and fixed quickly by the community. - Standardization: Using well-known middleware makes it easier for new developers to join your project because they likely already know how these tools work.
Common Third-Party Middleware
cors
By default, web browsers block scripts from making requests to a different domain than the one that served the page. The cors middleware allows you to bypass this or specifically whitelist which front-end applications (like a React or Vue app) are allowed to talk to your API.
Example:
const cors = require('cors');
const app = express();
// Allow all origins (common for public APIs)
app.use(cors());
// Or, restrict to a specific domain
app.use(cors({
origin: 'https://my-frontend-app.com'
}));
app.use(cors()) without arguments allows ANY website to make requests to your API. For production apps, always specify your allowed origins.
body-parser
When a user sends data (like a signup form or a JSON object), Express needs help reading that data. body-parser extracts the entire body portion of an incoming request stream and exposes it on req.body.
Example:
const bodyParser = require('body-parser');
const app = express();
// Parse incoming JSON requests
app.use(bodyParser.json());
// Parse URL-encoded data (from standard HTML forms)
app.use(bodyParser.urlencoded({ extended: true }));
express.json() instead of bodyParser.json() to reduce the number of packages you install.
morgan
Morgan is an HTTP request logger. It automatically prints details about every request coming into your server (the URL, the status code, and how long it took) to your console. This is indispensable for debugging.
Example:
const morgan = require('morgan');
const app = express();
// Use the 'dev' format for colorful, concise logs in the terminal
app.use(morgan('dev'));
helmet
Security is a massive topic, but helmet gives you a head start. It sets various HTTP headers to protect your app from common attacks like Cross-Site Scripting (XSS) and clickjacking.
Example:
const helmet = require('helmet');
const app = express();
// Automatically applies 15 different security headers
app.use(helmet());
express-session
HTTP is "stateless," meaning the server forgets who you are as soon as the request ends. express-session creates a session ID for each user, allowing you to store data like "isLoggedIn: true" across multiple pages.
Example:
const session = require('express-session');
const app = express();
app.use(session({
secret: 'keyboard cat', // Used to sign the session ID cookie
resave: false,
saveUninitialized: true,
cookie: { secure: true } // Only send over HTTPS
}));
process.env.SESSION_SECRET) to keep your credentials out of GitHub.
passport
Passport is the industry standard for authentication. It is extremely flexible and uses "strategies" to let users log in via a local database, Google, Facebook, or Twitter.
Example:
const passport = require('passport');
const app = express();
// Passport setup
app.use(passport.initialize());
app.use(passport.session());
express-validator
You should never trust user input. express-validator is a set of functions that check if data is in the correct format (e.g., is the email actually an email?) before you save it to your database.
Example:
const { body, validationResult } = require('express-validator');
app.post('/register', [
body('email').isEmail().withMessage('Enter a valid email'),
body('password').isLength({ min: 8 }).withMessage('Password too short')
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
res.send('Registration successful!');
});
rate-limiter-flexible
To prevent hackers from "brute-forcing" your login page or crashing your server with thousands of requests, you can use a rate limiter. It limits how many times an IP address can ping your server in a set timeframe.
Example:
const { RateLimiterMemory } = require('rate-limiter-flexible');
const rateLimiter = new RateLimiterMemory({
points: 10, // 10 requests
duration: 1, // per 1 second
});
app.use((req, res, next) => {
rateLimiter.consume(req.ip)
.then(() => next())
.catch(() => res.status(429).send('Stop spamming!'));
});
cookie-parser
This middleware reads the Cookie header from the browser and turns it into a handy object available at req.cookies.
Example:
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.get('/', (req, res) => {
console.log('Cookies: ', req.cookies);
});
multer
Standard body parsers cannot handle file uploads (like images). Multer is designed to handle "multipart/form-data," which is what browsers use when a user selects a file from their hard drive.
Example:
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
// 'avatar' is the name of the input field in your HTML form
app.post('/profile', upload.single('avatar'), (req, res) => {
// req.file contains info about the uploaded file
res.send('Profile picture updated!');
});
Example of Using Multiple Third-Party Middleware
In a real-world application, you will typically stack several middleware functions together. Order matters: security and logging usually come first.
const express = require('express');
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');
const app = express();
// 1. Security Headers
app.use(helmet());
// 2. Logging
app.use(morgan('dev'));
// 3. Cross-Origin Logic
app.use(cors());
// 4. Body Parsing
app.use(express.json());
// 5. Your Routes
app.get('/api/data', (req, res) => {
res.json({ message: "Secure, logged, and parsed!" });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Summary
Third-party middleware is what makes Express so powerful. By leveraging the work of thousands of developers, you can add complex features like file uploading, authentication, and advanced security headers with just a few lines of code. Always remember to install the packages via npm first, keep your secrets safe in environment variables, and pay close attention to the order in which you use app.use().