← 中文资源

简体中文版本

Express PayloadTooLargeError — 请求体超出限制

通过把 JSON 与 urlencoded 的限制与实际负载大小对齐,解决 Express body-parser 的 413 Entity Too Large,而非盲目调高限制。

阅读英文原文

症状

本篇调试指南针对“Express PayloadTooLargeError — 请求体超出限制”。内容涵盖可观察的症状、可复现的诊断路径、根本原因、具体修复方式,以及如何验证修复并防止回归。

可观察到的症状包括:

  • API 仅对较大提交返回 413 “request entity too large”
  • 较小的 JSON 成功,稍大的对象却返回 413
  • 错误来自 body-parser,而非你的路由处理器

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

curl -i -X POST https://api.example.com/items -H 'Content-Type: application/json' --data-binary @large.json

若 413 带有代理的 Server 头则是代理限制;若由 body-parser 记录则是应用限制。

步骤 2

wc -c large.json

与配置的限制对比;应略高于真实最大值,而不是设为无限。

步骤 3

grep -rn "bodyParser\|express.json" src/ | grep -i limit

配置的限制(或缺失时默认的 100kb)解释了阈值从何而来。

常见诱因(按出现频率排序):

  • 默认 100kb 的 JSON 限制小于正在发送的请求
  • 反向代理也限制请求体大小,在 Express 收到前就返回 413
  • 把 multipart 或大文本负载错误地送进了 JSON 解析器

根因

当流式请求体超过配置限制时,body-parser 立即拒绝并抛出 PayloadTooLargeError,早于处理器执行。前置代理还可能施加更小的第二层限制。

修复

为每个解析器设置明确且有界的限制(如 express.json({ limit: “1mb” })),把大文件上传改走流式/multipart 处理器,并把代理的 client_max_body_size 对齐为同一数值。

注意:不设上限的请求体是拒绝服务的入口,务必设置上限并校验 Content-Length。

import express from 'express';
const app = express();

app.use(express.json({ limit: '1mb' }));
app.use(express.urlencoded({ extended: true, limit: '1mb' }));

// 413 arrives before this handler when the limit is exceeded.
app.post('/items', (req, res) => res.json({ received: req.body }));

app.use((err, _req, res, _next) => {
  if (err.type === 'entity.too.large') return res.status(413).json({ error: 'payload too large' });
  res.status(500).json({ error: 'internal error' });
});

验证

先提交略小于新限制的负载确认 200,再提交略超限制的负载,确认返回受控的 413 与友好提示,而非崩溃。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。