Express Built-in Middleware
Introduction
Express.js, a popular web framework for Node.js, comes with several built-in middleware functions that handle common web application tasks. These middleware functions are ready to use without requiring additional installations, making it easier to set up basic functionality in your Express applications.
In this guide, we'll explore the built-in middleware that Express provides, understand their purposes, and learn how to implement them in your applications.
What is Express Middleware?
Before diving into built-in middleware, let's quickly recap what middleware is in Express:
Middleware functions are functions that have access to the request object (req
), the response object (res
), and the next middleware function in the application's request-response cycle. These functions can:
- Execute code
- Make changes to the request and response objects
- End the request-response cycle
- Call the next middleware function
Express Built-in Middleware Overview
Express comes with the following built-in middleware functions:
express.static
- Serves static filesexpress.json
- Parses incoming requests with JSON payloadsexpress.urlencoded
- Parses incoming requests with URL-encoded payloadsexpress.text
- Parses incoming requests with text payloadsexpress.raw
- Parses incoming requests with raw body payloads
Let's explore each of these in detail.
1. express.static
This middleware function serves static files such as images, CSS files, and JavaScript files. It's based on the serve-static
module.
Basic Usage
const express = require('express');
const app = express();
const path = require('path');
// Serve static files from the 'public' directory
app.use(express.static('public'));
// You can also specify a mount path
app.use('/static', express.static('public'));
// Using absolute path (recommended)
app.use(express.static(path.join(__dirname, 'public')));
Example Directory Structure
/project-root
/public
/css
style.css
/js
script.js
/images
logo.png
server.js
How It Works
When you use express.static('public')
, files in the public directory become accessible at the root URL:
http://localhost:3000/css/style.css
serves the file/public/css/style.css
http://localhost:3000/js/script.js
serves the file/public/js/script.js
http://localhost:3000/images/logo.png
serves the file/public/images/logo.png
When you use app.use('/static', express.static('public'))
, the files are served under the /static
path:
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/script.js
http://localhost:3000/static/images/logo.png
Options
The express.static
function accepts an options object as its second argument:
app.use(express.static('public', {
dotfiles: 'ignore', // How to treat dotfiles (default: 'ignore')
etag: true, // Enable or disable etag generation (default: true)
extensions: ['html'], // File extension fallbacks
index: 'index.html', // Default file name (default: 'index.html')
maxAge: '1d', // Set Cache-Control header max-age in milliseconds or string format
redirect: true, // Redirect to trailing '/' when pathname is a directory
setHeaders: function (res, path, stat) {
// Custom function to set HTTP headers
res.set('x-timestamp', Date.now());
}
}));
2. express.json
This middleware parses incoming requests with JSON payloads. It's based on the body-parser
module.
Basic Usage
const express = require('express');
const app = express();
// Parse JSON bodies
app.use(express.json());
// Create a POST endpoint
app.post('/api/data', (req, res) => {
console.log(req.body); // Access the parsed JSON data
res.json({ message: 'Data received', data: req.body });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Example Request and Response
Using curl or any HTTP client:
POST /api/data HTTP/1.1
Host: localhost:3000
Content-Type: application/json
{
"name": "John Doe",
"email": "[email protected]"
}
Response:
{
"message": "Data received",
"data": {
"name": "John Doe",
"email": "[email protected]"
}
}
Options
The express.json
function accepts an options object:
app.use(express.json({
inflate: true, // Allows deflated (compressed) bodies
limit: '100kb', // Controls the maximum request body size
reviver: null, // Function passed to JSON.parse()
strict: true, // Enables only accepting arrays and objects
type: 'application/json', // Request Content-Type to parse
verify: undefined // Function to verify body content
}));
3. express.urlencoded
This middleware parses incoming requests with URL-encoded payloads (typically from HTML forms).
Basic Usage
const express = require('express');
const app = express();
// Parse URL-encoded bodies (as sent by HTML forms)
app.use(express.urlencoded({ extended: true }));
// Create a route to handle form submissions
app.post('/submit-form', (req, res) => {
console.log(req.body); // Access the form data
res.send(`Form submitted! Name: ${req.body.name}`);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
HTML Form Example
<form action="/submit-form" method="POST">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<button type="submit">Submit</button>
</form>
Options
The express.urlencoded
function accepts an options object:
app.use(express.urlencoded({
extended: true, // Use the qs library (true) or querystring library (false)
inflate: true, // Allows deflated (compressed) bodies
limit: '100kb', // Controls the maximum request body size
parameterLimit: 1000, // Maximum number of parameters
type: 'application/x-www-form-urlencoded', // Request Content-Type to parse
verify: undefined // Function to verify body content
}));
4. express.text
This middleware parses incoming requests with text payloads.
Basic Usage
const express = require('express');
const app = express();
// Parse text bodies
app.use(express.text());
app.post('/receive-text', (req, res) => {
console.log(req.body); // Access the text content
res.send(`Received: ${req.body}`);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Example Request
POST /receive-text HTTP/1.1
Host: localhost:3000
Content-Type: text/plain
Hello, world! This is a text message.
Options
The express.text
function accepts an options object:
app.use(express.text({
defaultCharset: 'utf-8', // Default charset
inflate: true, // Allows deflated (compressed) bodies
limit: '100kb', // Controls the maximum request body size
type: 'text/plain' // Request Content-Type to parse
}));
5. express.raw
This middleware parses incoming request bodies into a Buffer. It's useful when you need to handle binary data.
Basic Usage
const express = require('express');
const app = express();
// Parse raw bodies into Buffer
app.use(express.raw());
app.post('/upload-binary', (req, res) => {
console.log(req.body); // Buffer containing the raw data
console.log(`Received ${req.body.length} bytes of data`);
res.send(`Received ${req.body.length} bytes of data`);
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Options
The express.raw
function accepts an options object:
app.use(express.raw({
inflate: true, // Allows deflated (compressed) bodies
limit: '100kb', // Controls the maximum request body size
type: 'application/octet-stream' // Request Content-Type to parse
}));
Real-world Application Example
Let's build a simple API server that demonstrates all the built-in middleware:
const express = require('express');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;
// Static file server
app.use(express.static(path.join(__dirname, 'public')));
// Parse JSON requests
app.use(express.json());
// Parse URL-encoded form data
app.use(express.urlencoded({ extended: true }));
// Parse text content
app.use(express.text());
// Parse raw binary data
app.use(express.raw({ type: 'application/octet-stream' }));
// API routes
app.get('/api/hello', (req, res) => {
res.json({ message: 'Hello from Express!' });
});
app.post('/api/user', (req, res) => {
// Handles JSON data
console.log('User data:', req.body);
res.status(201).json({
message: 'User created successfully',
user: req.body
});
});
app.post('/api/form', (req, res) => {
// Handles form data
console.log('Form data:', req.body);
res.send(`Form received with name: ${req.body.name}`);
});
app.post('/api/message', (req, res) => {
// Handles text data
console.log('Message:', req.body);
res.send(`Message received: ${req.body.substring(0, 50)}...`);
});
app.post('/api/binary', (req, res) => {
// Handles binary data
console.log(`Received ${req.body.length} bytes of binary data`);
res.send(`Received ${req.body.length} bytes of binary data`);
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
With this setup, your server can handle various types of incoming requests, making it versatile for different client needs.
Best Practices
-
Always specify size limits to prevent denial-of-service attacks:
javascriptapp.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ limit: '1mb', extended: true })); -
Use absolute paths with
express.static
to avoid path resolution issues:javascriptapp.use(express.static(path.join(__dirname, 'public')));
-
Add appropriate Content-Type headers in your client requests:
application/json
for JSON dataapplication/x-www-form-urlencoded
for form datatext/plain
for text dataapplication/octet-stream
for binary data
-
Apply middleware selectively to specific routes when needed:
javascriptapp.post('/api/upload', express.raw({ type: 'image/*', limit: '5mb' }), (req, res) => {
// Handle image upload
});
Summary
Express built-in middleware functions are powerful tools that simplify common web server tasks:
express.static
: Serves static files like HTML, CSS, images, and client-side JavaScriptexpress.json
: Parses incoming JSON payloadsexpress.urlencoded
: Parses form data submissionsexpress.text
: Handles plain text requestsexpress.raw
: Processes binary data
These middleware functions handle the heavy lifting of request parsing and static file serving, allowing you to focus on building your application's business logic.
Additional Resources
- Express.js Official Documentation on Middleware
- Express.js API Reference for Built-in Middleware
- body-parser Documentation - The module that powers Express's body parsing middleware
- serve-static Documentation - The module behind Express's static file serving
Exercises
- Create a simple API that accepts both JSON and URL-encoded form data, and responds with the received data.
- Set up a static file server with custom Cache-Control headers for different file types.
- Build a file upload server that can handle both form uploads and raw binary data.
- Create a text processing API that accepts plain text submissions and performs operations like word counting, spell checking, or text summarization.
- Implement size and content-type validation for all incoming requests to improve your application's security.
Happy coding with Express middleware!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)