如何测试代理链路中的 Expect: 100-continue 大文件上传

大型上传的重复成本很高。HTTP Expect: 100-continue 允许 HTTP/1.1 客户端先发送请求头并短暂等待;若服务器仅凭方法、路径或凭据就能拒绝请求,客户端无需先传完整正文。代理可能通过删除请求头、吞掉临时响应、延迟超过客户端计时器、在错误节点生成响应,或在最终拒绝前提前转发正文,破坏这项机制。
本指南用于代理采购与运维验收。只测试自有或获授权的端点和文件,不得未经许可探测第三方上传服务。
明确预期交换
客户端发送请求行和请求头(含 Expect: 100-continue),暂不发送正文。HTTP/1.1 源站可以依据请求头立即返回最终拒绝,或先返回 100 Continue,正文收完后再返回唯一最终响应。中间设备通常应转发信息性响应,除非预期是它自行添加的。
客户端不能无限等待。若在配置的预期计时器内没有收到临时或最终响应,它可能开始发送正文。计时器属于客户端行为,因此测试必须记录时序,不能假设所有库一致。
HTTP/2 与 HTTP/3 可以终止单个请求流而不关闭整条连接,客户端未必以相同方式使用该机制。应分别记录代理两侧的实际协议,不要假定 HTTP/1.1 交换在协议转换后完全不变。
建立自有上传夹具
创建包含四种确定模式的实验端点:
| 模式 | 请求头阶段 | 正文预期 |
|---|---|---|
| 接受 | 返回100,再返回最终成功 | 完整正文只接收一次 |
| 未授权 | 正文前返回最终401 | 不接收正文 |
| 不支持预期 | 返回最终417 | 仅按明确策略决定是否重试 |
| 延迟 | 控制临时响应延迟 | 测出客户端等待阈值 |
使用不同大小的合成非敏感载荷。记录载荷摘要、声明长度、实收长度与最终摘要,并让服务端统计每个响应前后收到的字节数。
按阶段采集证据
每次记录测试编号、路由别名、客户端版本、客户端到代理协议、代理到源站协议、是否看见 Expect、首个临时状态、临时响应耗时、正文开始时间、最终响应前字节数、最终状态、实收字节、摘要是否匹配、连接是否复用及重试次数。
路由和会话标识只保留哈希,不记录代理密码、认证头、Cookie、令牌或私有载荷。
先建立直连基线
使用真实生产客户端,在不经过代理时运行全部模式。确认接受模式在 100 后只发送一次正文;请求头阶段的 401 不发送正文;417 符合客户端文档策略;延迟模式能暴露实际等待计时器。
同时测试小型和大型载荷。部分客户端会根据正文大小、方法或长度是否已知来添加或抑制 Expect。以线路证据为准,不能只看命令配置。
逐条加入代理路径
分别测试每个网关、区域、认证方式和地址族,固定客户端、载荷、端点与超时。比较源站是否收到 Expect、客户端是否收到 100、正文是否提前开始、最终拒绝是否停止正文、协议转换是否改变顺序,以及最终响应后连接能否安全复用。
请求头消失或变化时,使用代理请求头完整性测试;最终结果可结合代理响应完整性测试验证。
验证提前拒绝节省带宽
在未授权模式中,仅使用故意无效的实验凭据。端点应依据请求头返回最终 401,健康链路不应继续上传大型正文。
同时测量客户端发送字节与源站接收字节。即使源站没有收到,代理仍可能缓冲数据,所以两个视角都重要。负面测试不得使用真实凭据。
安全处理 417
417 Expectation Failed 表示响应链不支持该预期。部分客户端可能不带 Expect 再次请求,但这不意味着所有自动重试都安全。
只有当应用能够证明首次操作未生效,或服务接受幂等机制时才允许重试。限制请求次数、总时长与字节数,并在规模化启用回退前使用重试风暴预防指南。
常见故障归因
| 现象 | 可能原因 |
|---|---|
| 每次上传前固定停顿 | 客户端等待未到达的100 |
| 源站看到Expect,客户端没看到100 | 代理或协议转换吞掉临时响应 |
| 源站从未看到Expect | 客户端抑制或代理删除 |
| 拒绝前正文已经到达 | 计时器到期、代理提前缓冲或客户端未等待 |
| 401 后仍传完整正文 | 响应处理或缓冲错误 |
| 收到两份完整正文 | 417或传输重试失控 |
| 只有直连成功 | 网关处理、协议转换或超时不匹配 |
不要把所有延迟都归因于出口 IP 质量。在路由证据证明前,它首先是消息流与时序问题。
验收门槛
路由只有在以下条件全部满足时才通过:接受模式产生一个校验通过的正文和一个最终响应;请求头阶段拒绝能避免不必要上传;临时与最终响应顺序正确;计时器有界;重试不会复制应用效果;日志能定位失败阶段且不含秘密。
还应跟踪临时响应耗时、拒绝节省字节、完整上传率、重复正文率、最终响应延迟和每次验证成功上传成本。单看吞吐量无法证明握手正确。
发布检查清单
- 已掌握确切客户端版本的直连行为。
- 已测试小型、大型、已知长度与流式正文。
- 已记录代理两侧协议。
- 已覆盖接受、401、417与延迟模式。
- 已比较客户端和源站字节计数。
- 每个接受请求只产生一次业务结果。
- 最终拒绝能够停止正文。
- Expect计时器与上传总期限有界。
- 重试必须可安全重放或具备幂等性。
- 日志不含凭据和私有内容。
常见问题
所有上传都应该使用 Expect: 100-continue 吗?
不应该。对小正文,额外往返的成本可能高于节省。应测试客户端阈值和业务拒绝概率。
没有收到100一定是代理故障吗?
不一定。服务器可以立即返回最终响应,客户端也可能在计时器到期后开始发送。需要比较直连与代理线路证据。
收到100是否代表上传成功?
不是。它只说明初始请求尚未被拒绝,客户端仍需接收并验证最终响应。
417是否应该触发代理轮换?
不应该。它描述响应链对预期的支持,不代表住宅 IP 信誉。应先诊断协议路径。
合规说明
上传和拒绝测试只能针对自有或明确获授权的系统。遵守服务限制、数据规则和代理政策;使用合成载荷并最小化保留,不得利用代理轮换绕过上传拒绝或访问控制。