Express.js
Request body, Content-Type y parsing
Transformación segura del body desde bytes y Content-Type hasta parsing, validación y límites semánticos.
- Última actualización
- Actualizada
- Nivel
- Fundamentos
Express.js
Transformación segura del body desde bytes y Content-Type hasta parsing, validación y límites semánticos.
request.body solo existe cuando un parser compatible consumió el stream. El parser utiliza Content-Type, límites y opciones para producir un valor JavaScript.
bytes
→ parser según media type
→ valor no confiable
→ validación de runtime
→ input de aplicaciónLeer manualmente un stream exige controlar chunks, encoding, tamaño, errores, abort y finalización. Express incluye parsers para casos habituales, pero no conoce la estructura que tu endpoint necesita.
Content-Type describe la representación enviada:
application/json
application/x-www-form-urlencoded
text/plain; charset=utf-8
application/octet-stream
multipart/form-data; boundary=...Accept describe lo que el cliente desea recibir; no sustituye Content-Type.
app.use(express.json({
limit: '100kb',
strict: true,
type: ['application/json', 'application/*+json'],
}));El parser comprueba sintaxis JSON y tamaño. No garantiza que el resultado sea un objeto con campos correctos.
null[1, 2, 3]ambos son JSON válido, aunque el endpoint espere { "items": [...] }.
app.use(express.urlencoded({
extended: false,
limit: '50kb',
parameterLimit: 100,
}));Es común en formularios HTML. extended afecta estructuras anidadas y parser utilizado. Aceptar profundidad ilimitada puede aumentar complejidad y riesgo.
app.use('/webhooks/provider', express.raw({
type: 'application/json',
limit: '1mb',
}));Los webhooks firmados suelen necesitar los bytes exactos. Si express.json() consume antes el stream, reserializar el objeto no reproduce necesariamente la secuencia firmada.
app.use('/webhooks/provider', express.raw({ type: 'application/json' }));
app.use(express.json({ limit: '100kb' }));El parser específico debe ejecutarse antes del general. Otra opción es usar la opción verify para capturar raw body, pero debe diseñarse conscientemente.
express.json() no procesa archivos multipart. Herramientas como Busboy o Multer interpretan boundaries y streams. Aun así debes limitar:
El nombre y MIME type enviados por el cliente no son prueba del contenido real.
Diferencia:
{}nullUn DELETE puede no requerir body; un POST /orders probablemente sí. El contrato del endpoint decide.
JSON inválido ocurre antes del handler:
{ "items": [ }El error middleware debe mapearlo a un error público como INVALID_JSON, sin exponer stack ni internals del parser.
El límite de bytes es una primera defensa. También importa el coste posterior:
La validación debe imponer límites semánticos además del parser.
No asumas que cualquier charset es aceptable. Si el media type no está soportado, responde 415. Si el body es ilegible o la sintaxis inválida, normalmente corresponde 400.
const createOrderBodySchema = z.object({
items: z.array(z.object({
productId: z.string().uuid(),
quantity: z.number().int().min(1).max(100),
})).min(1).max(50),
}).strict();
router.post('/', (request, response, next) => {
const result = createOrderBodySchema.safeParse(request.body);
if (!result.success) {
next(new RequestValidationError(result.error));
return;
}
response.locals.validatedBody = result.data;
next();
}, createOrderHandler);Flujo:
No adivines siempre. Puedes rechazar 415 cuando la operación requiere JSON.
La validación estructural pasa, pero el caso de uso puede rechazar stock, estado o permisos.
La descompresión puede amplificar tamaño. Coordina límites y proxies.
El parser o middleware debe limpiar archivos temporales y detener procesamiento.
El primero consume el stream; el segundo no puede volver a leerlo.
express.json() después del router.Content-Type o filename.Incluye:
Parsers globales simplifican configuración, pero consumen recursos en rutas que quizá no los necesitan. Parsers por router o path aumentan precisión a costa de más configuración.
Content-Type selecciona interpretación.Construir responses HTTP correctas transforma resultados internos en status, headers y representaciones públicas.