express.json() body parser 크기 제한
Configuring body parser size limits in Express.js to prevent memory exhaustion from oversized JSON payloads.
express.json() body parser 크기 제한
Introduction
By default, Express.js body parser accepts JSON payloads up to 100KB. While this protects against most abuse scenarios, legitimate use cases like file uploads via base64 or batch operations may require larger limits. Understanding how to configure this properly is essential for both security and functionality.
Environment
node --version
# v20.11.0
npm list express
# my-app@1.0.0
# +-- express@4.18.2Problem
A batch import endpoint was failing with a cryptic error:
app.post('/api/batch-import', (req, res) => {
console.log(req.body);
// undefined for large payloads
res.json({ received: true });
});PayloadTooLargeError: request entity too large
at readStream (node:internal/stream_base_commons:169:17)
at inbound (node:_http_server:681:13)The issue was that the default 100KB limit was too small for the batch operation, but setting no limit exposed the server to denial of service attacks.
Analysis
The body parser configuration in Express affects three things:
- Maximum payload size - How large a request body can be
- Character encoding - How the body is decoded
- Type checking - Which content types are parsed
The default configuration:
// What express.json() does internally
app.use(express.json({ limit: '100kb' }));When a payload exceeds the limit, the connection is terminated immediately.
Solution
Solution 1: Configure a larger limit for specific routes
const express = require('express');
const app = express();
// Default limit for most routes
app.use(express.json({ limit: '100kb' }));
// Larger limit for batch import
app.post('/api/batch-import',
express.json({ limit: '10mb' }),
(req, res) => {
res.json({ received: true, items: req.body.items?.length });
}
);Solution 2: Multiple limits based on route patterns
app.use(express.json({ limit: '100kb' }));
// Increase limit for specific routes
app.use('/api/uploads', express.json({ limit: '50mb' }));
app.use('/api/batch', express.json({ limit: '10mb' }));
app.use('/api/webhooks', express.json({ limit: '1mb' }));Solution 3: Complete body parser configuration
app.use(express.json({
limit: '1mb',
verify: (req, res, buf) => {
// Store the raw body for signature verification
req.rawBody = buf;
},
type: 'application/json'
}));
app.use(express.urlencoded({
extended: true,
limit: '100kb'
}));Solution 4: Custom body parser with validation
function createBodyParser(maxSize) {
return express.json({
limit: maxSize,
verify: (req, res, buf, encoding) => {
if (buf.length > parseInt(maxSize)) {
throw new Error('Payload too large');
}
}
});
}
// Use different parsers for different routes
app.post('/api/small', createBodyParser('100kb'), handler);
app.post('/api/large', createBodyParser('10mb'), handler);Solution 5: Monitoring payload sizes
app.use((req, res, next) => {
let data = '';
req.on('data', chunk => {
data += chunk;
// Monitor size during upload
if (data.length > 10 * 1024 * 1024) { // 10MB warning
console.warn(`Large payload detected: ${req.path} - ${data.length} bytes`);
}
});
req.on('end', () => {
req.bodySize = data.length;
});
next();
});
// Log request sizes
app.use((req, res, next) => {
if (req.bodySize) {
console.log(`${req.method} ${req.path} - ${req.bodySize} bytes`);
}
next();
});Lessons Learned
- Never set limit to
falseor extremely high - It opens you to DoS attacks - Use per-route limits instead of global limits when different routes have different needs
- Monitor payload sizes - Unexpectedly large payloads may indicate an attack
- Set appropriate limits for webhooks - External services may send large payloads
- Consider streaming for very large payloads - Do not load everything into memory
This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.