When building web applications, especially APIs, one of the most common tasks is handling incoming data sent from clients. This data often comes in the form of an HTTP request body, which can contain JSON, form data, or other formats. To make it easier to work with this data, Express.js provides middleware for parsing different types of request bodies. This middleware is known as Body Parsing Middleware.
Middleware in Express.js is a function that runs between receiving a request and sending a response. Middleware functions have access to the req
(request) and res
(response) objects and can modify them, execute code, or terminate the request-response cycle. Body parsing middleware specifically deals with extracting the body of incoming requests so that it can be easily accessed and manipulated.
In this chapter, we’ll explore:
When a client sends data to a server using an HTTP POST, PUT, or PATCH request, the data is often included in the request body. Body parsing is the process of reading this data and converting it into a format that can be easily used in your application, typically a JavaScript object.
Without body parsing middleware, the request body is received as a raw stream of data, which isn’t very useful in most cases. The body parsing middleware reads this stream, processes it, and attaches the parsed data to the req.body
object.
Body parsing is crucial because:
Express.js provides a built-in middleware function called express.json()
for parsing JSON request bodies. It also provides express.urlencoded()
for parsing URL-encoded data (typically from HTML forms).
These middleware functions are added to your Express application and are automatically executed when a request is received, processing the body and attaching the parsed data to req.body
.
The express.json()
middleware is used to parse JSON-formatted request bodies. JSON (JavaScript Object Notation) is the most common format for sending data in web applications, especially in APIs.
Let’s create an Express.js application that handles a POST request with a JSON body.
app.js
const express = require('express');
const app = express();
const port = 3000;
// Use express.json() to parse JSON bodies
app.use(express.json());
app.post('/data', (req, res) => {
const data = req.body;
res.json({
message: 'Data received successfully',
receivedData: data,
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
req.body
with the resulting object./data
route responds with the received JSON data.If you send a POST request to http://localhost:3000/data
with the following JSON body:
{
"name": "John Doe",
"age": 30
}
The server will respond with:
{
"message": "Data received successfully",
"receivedData": {
"name": "John Doe",
"age": 30
}
}
The express.urlencoded()
middleware is used to parse URL-encoded bodies, typically from HTML forms. URL-encoded data is formatted as key-value pairs, with special characters encoded using percent-encoding.
Let’s modify our example to handle form submissions using URL-encoded data.
app.js
// Use express.urlencoded() to parse URL-encoded bodies
app.use(express.urlencoded({ extended: true }));
app.post('/submit-form', (req, res) => {
const formData = req.body;
res.json({
message: 'Form submitted successfully',
receivedData: formData,
});
});
req.body
. The extended
option allows you to choose between the built-in querystring
library (extended: false
) and the qs
library (extended: true
) for parsing./submit-form
route responds with the received form data.If you submit a form to http://localhost:3000/submit-form
with the following data:
The server will respond with:
{
"message": "Form submitted successfully",
"receivedData": {
"name": "John Doe",
"age": "30"
}
}
The express.text()
middleware is used to parse plain text request bodies. This is useful when you expect raw text input from the client.
Let’s create an example where the server accepts and responds with plain text.
app.js
// Use express.text() to parse text bodies
app.use(express.text());
app.post('/text', (req, res) => {
const text = req.body;
res.send(`Received text: ${text}`);
});
req.body
./text
route responds with the received text.If you send a POST request to http://localhost:3000/text
with the following body:
Hello, world!
The server will respond with:
Received text: Hello, world!
The express.raw()
middleware is used to parse the request body as a raw buffer. This is useful when dealing with binary data or non-standard formats.
Let’s create an example where the server accepts raw binary data.
app.js
// Use express.raw() to parse raw bodies
app.use(express.raw({ type: 'application/octet-stream' }));
app.post('/binary', (req, res) => {
const binaryData = req.body;
res.send(`Received ${binaryData.length} bytes of binary data`);
});
Content-Type
matches application/octet-stream
./binary
route responds with the length of the received binary data.If you send a POST request to http://localhost:3000/binary
with some binary data, the server will respond with something like:
Received 256 bytes of binary data
When dealing with large request bodies, it’s essential to consider performance and security. By default, Express limits the size of the request body to 100KB for express.json()
and express.urlencoded()
.
Let’s modify our JSON example to handle larger payloads by increasing the limit.
app.js
// Configure express.json() to handle larger payloads
app.use(express.json({ limit: '1mb' }));
app.post('/large-data', (req, res) => {
const data = req.body;
res.json({
message: 'Large data received successfully',
receivedData: data,
});
});
/large-data
route can now handle larger JSON bodies without issues.When parsing request bodies, it’s crucial to validate and sanitize the incoming data to prevent common security vulnerabilities, such as:
Let’s add error handling to ensure that our application responds gracefully to invalid JSON bodies.
app.js
app.use(express.json());
// Error handling middleware
app.use((err, req, res, next) => {
if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
return res.status(400).json({ error: 'Invalid JSON' });
}
next();
});
app.post('/data', (req, res) => {
const data = req.body;
res.json({
message: 'Data received successfully',
receivedData: data,
});
});
SyntaxError
to catch invalid JSON bodies and responds with a 400 Bad Request
status.In some cases, you may need to implement custom body parsing logic to handle non-standard formats or complex requirements.
Let’s create a custom middleware to parse a simple key-value pair format.
app.js
// Custom middleware to parse key-value format (e.g., "key1:value1;key2:value2")
function customBodyParser(req, res, next) {
if (req.headers['content-type'] === 'text/custom') {
let body = '';
req.on('data', (chunk) => {
body += chunk.toString();
});
req.on('end', () => {
const parsedBody = {};
body.split(';').forEach(pair => {
const [key, value] = pair.split(':');
parsedBody[key] = value;
});
req.body = parsedBody;
next();
});
} else {
next();
}
}
// Use the custom body parser
app.use(customBodyParser);
app.post('/custom-data', (req, res) => {
const data = req.body;
res.json({
message: 'Custom data received successfully',
receivedData: data,
});
});
Content-Type
and parses the request body accordingly. The parsed data is then attached to req.body
./custom-data
route handles this custom format and responds with the parsed data.If you send a POST request to http://localhost:3000/custom-data
with the following body:
key1:value1;key2:value2
The server will respond with:
{
"message": "Custom data received successfully",
"receivedData": {
"key1": "value1",
"key2": "value2"
}
}
In this chapter, we covered everything you need to know about Body Parsing Middleware in Express.js, from basic concepts to advanced scenarios. Understanding how to parse and handle request bodies is a fundamental skill when building web applications and APIs. Happy coding !❤️