mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-26 20:33:15 +00:00
http.Server 原本**一个超时都没设**(只有 Handler)。后果是 Slowloris: 攻击者只占连接不发完整请求头,每个连接挂几 KB。MaxHeaderBytes 限的是 头部**大小**,「慢慢发」不占大小、不受它约束,几百个连接就能耗尽 fd。 ## 为什么不是「把超时都设上」 webui 有一条长连接 SSE(/api/v1/chat/events)与可跑 300s 的流式 /v1/chat/completions。WriteTimeout 是「从请求开始到响应写完」的**总预算**, 会把它们腰斩 —— 表现为 SSE 每隔一段时间断一次、前端疯狂重连。而这类 回归在功能测试里很难立刻发现。 所以只设读侧三项,各管一段: ReadHeaderTimeout 20s —— 请求头必须按时发完,Slowloris 的正解 ReadTimeout 60s —— 读完整请求(含 body)的预算,防慢速上传 IdleTimeout 120s —— keep-alive 空闲连接(另两项都管不到) WriteTimeout 0 —— **刻意不设**(见上) ## 判据(3 条,含一条反向判据) - TestServerHasReadSideTimeouts:三个读侧超时都必须 > 0 - TestServerHasNoWriteTimeout:**反向**钉住 WriteTimeout 必须保持 0, 防止将来有人「顺手补全超时」把 SSE 弄坏 - TestSSEConnectionSurvivesBeyondReadTimeout:SSE 连接确实活过读侧窗口 反向判据看着琐碎,但它守的正是「这次没做的那件事」—— 不加 WriteTimeout 是个**决定**,不是疏漏,所以要用判据把决定固定下来。 变异验证:补上 WriteTimeout:30s → 反向判据判红; 去掉 ReadHeaderTimeout → 前向判据判红。 测试脚手架注意:newServerForTest 绑 127.0.0.1:0(内核分配空闲端口), 绝不用 :8080 —— 那是生产端口(见 a752ae1)。 全量:35 包全绿。