Express Request Body
Introduction
When building web applications, you often need to handle data sent by clients through HTTP requests. This data is contained in what's called the request body. Unlike URL parameters or query strings that appear in the URL itself, the request body can contain larger amounts of data and is typically sent with POST, PUT, PATCH, or DELETE requests.
In Express.js, accessing the request body isn't available by default - you need to use middleware to parse this data into a usable format. This guide will teach you how to access and process request body data in your Express applications.
Understanding Request Bodies
A request body can contain data in various formats:
- JSON data: Used in API requests
- Form data: Submitted from HTML forms
- Text: Plain text content
- Binary data: Files and other binary content
Before we can access this data in our Express application, we need to set up the appropriate middleware.
Setting Up Body Parsing Middleware
Express provides built-in middleware to parse different types of request bodies:
1. JSON Body Parser
To handle JSON data sent in request bodies:
const express = require('express');
const app = express();
// Add JSON body parser middleware
app.use(express.json());
This middleware parses JSON request bodies and makes the data available on the req.body
property.
2. URL-Encoded Body Parser
For handling form submissions:
// Parse URL-encoded bodies (form data)
app.use(express.urlencoded({ extended: true }));
The extended: true
option allows for parsing rich objects and arrays in the URL-encoded format using the qs library.
3. Text Body Parser
For plain text request bodies:
// Parse plain text bodies
app.use(express.text());
4. Raw Body Parser
For raw binary data:
// Parse raw binary data
app.use(express.raw({ type: 'application/octet-stream' }));
Accessing Request Body Data
Once you've set up the appropriate middleware, accessing the request body is straightforward:
app.post('/users', (req, res) => {
// The parsed body is available as req.body
const userData = req.body;
console.log(userData);
// Process the data...
res.json({
message: "User data received",
user: userData
});
});
Complete Example: Processing JSON Data
Here's a complete example of an Express server that processes JSON data:
const express = require('express');
const app = express();
const PORT = 3000;
// Add middleware to parse JSON bodies
app.use(express.json());
// Route that handles POST requests with JSON data
app.post('/api/users', (req, res) => {
// Access the request body data
const { name, email, age } = req.body;
// Validate the data
if (!name || !email) {
return res.status(400).json({ error: 'Name and email are required' });
}
// Process the data (in a real app, you might save to a database)
const newUser = {
id: Date.now(),
name,
email,
age: age || null,
createdAt: new Date()
};
res.status(201).json({
message: 'User created successfully',
user: newUser
});
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Testing with cURL
You can test this endpoint using cURL:
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"John Doe","email":"[email protected]","age":30}'
Expected output:
{
"message": "User created successfully",
"user": {
"id": 1621234567890,
"name": "John Doe",
"email": "[email protected]",
"age": 30,
"createdAt": "2023-05-17T12:34:56.789Z"
}
}
Processing Form Data
HTML forms are a common way to send data to a server. Here's how to handle form submissions:
const express = require('express');
const app = express();
const PORT = 3000;
// Add middleware to parse URL-encoded bodies (form data)
app.use(express.urlencoded({ extended: true }));
// Serve a simple HTML form
app.get('/form', (req, res) => {
res.send(`
<html>
<body>
<h1>Submit Feedback</h1>
<form method="POST" action="/submit-feedback">
<div>
<label>Name:</label>
<input type="text" name="name" required>
</div>
<div>
<label>Email:</label>
<input type="email" name="email" required>
</div>
<div>
<label>Message:</label>
<textarea name="message" required></textarea>
</div>
<button type="submit">Submit</button>
</form>
</body>
</html>
`);
});
// Handle form submission
app.post('/submit-feedback', (req, res) => {
const { name, email, message } = req.body;
// Validate form data
if (!name || !email || !message) {
return res.status(400).send('All fields are required');
}
// In a real application, you might save this to a database
console.log('Received feedback:', { name, email, message });
// Send a response
res.send(`
<html>
<body>
<h1>Thank you for your feedback!</h1>
<p>We received your message, ${name}.</p>
<a href="/form">Submit another feedback</a>
</body>
</html>
`);
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Handling File Uploads
For file uploads, you'll need additional middleware like multer
:
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const PORT = 3000;
// Configure storage
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`);
}
});
const upload = multer({ storage });
app.get('/upload', (req, res) => {
res.send(`
<html>
<body>
<h1>File Upload</h1>
<form method="POST" action="/upload-file" enctype="multipart/form-data">
<div>
<label>Select file:</label>
<input type="file" name="document" required>
</div>
<button type="submit">Upload</button>
</form>
</body>
</html>
`);
});
// Handle single file upload
app.post('/upload-file', upload.single('document'), (req, res) => {
if (!req.file) {
return res.status(400).send('No file was uploaded');
}
res.send(`
<html>
<body>
<h1>File Uploaded Successfully</h1>
<p>File name: ${req.file.originalname}</p>
<p>Size: ${req.file.size} bytes</p>
</body>
</html>
`);
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Body Size Limits
By default, Express body parsers limit the size of the request body to protect against malicious attacks. You can configure these limits:
// Limit JSON bodies to 1MB
app.use(express.json({ limit: '1mb' }));
// Limit URL-encoded bodies to 2MB
app.use(express.urlencoded({ extended: true, limit: '2mb' }));
Best Practices
- Always validate request bodies: Never trust client-sent data without validation.
- Set appropriate size limits: Configure body size limits to prevent abuse.
- Handle parsing errors: Use error handling middleware to catch JSON parsing errors.
- Content-Type verification: Verify that the content type matches what you expect.
Here's an example that incorporates these best practices:
const express = require('express');
const app = express();
// Configure body parsers with size limits
app.use(express.json({
limit: '1mb',
verify: (req, res, buf) => {
try {
JSON.parse(buf);
} catch(e) {
res.status(400).json({ error: 'Invalid JSON' });
throw new Error('Invalid JSON');
}
}
}));
app.use(express.urlencoded({
extended: true,
limit: '1mb'
}));
// Error handling middleware for JSON parsing errors
app.use((err, req, res, next) => {
if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
return res.status(400).json({ error: 'Bad request - Invalid JSON' });
}
next();
});
app.post('/api/data', (req, res) => {
// Content-Type verification
const contentType = req.headers['content-type'];
if (!contentType || !contentType.includes('application/json')) {
return res.status(415).json({ error: 'Content-Type must be application/json' });
}
// Data validation
const { username, email } = req.body;
if (!username || typeof username !== 'string') {
return res.status(400).json({ error: 'Valid username is required' });
}
if (!email || !email.includes('@')) {
return res.status(400).json({ error: 'Valid email is required' });
}
res.json({ success: true, message: 'Data received successfully' });
});
app.listen(3000);
Summary
In this guide, you learned:
- How to set up middleware to parse different types of request bodies in Express
- How to access and process data from request bodies
- How to handle form submissions and file uploads
- Best practices for working with request body data
Understanding how to work with request bodies is essential for building robust Express applications that can receive and process data from clients.
Additional Resources
- Express.js Documentation on Middleware
- Multer Documentation for file uploads
- Body Parser Documentation for advanced body parsing options
Exercises
- Create a simple API endpoint that receives a list of items in a shopping cart and calculates the total price.
- Build a contact form that sends data to an Express server, validates it, and responds with a confirmation.
- Create an image upload system that validates file types and sizes before saving them.
- Implement an API endpoint that accepts nested JSON data, validates it thoroughly, and responds with appropriate error messages.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)