EarlyData 是 TLS 层特性而非 Fiber 中间件,Fiber 仅能通过 Nginx 透传的 Early-Data 请求头被动识别 0-RTT;需 Nginx 正确配置 ssl_early_data、TLS 版本、会话缓存及 proxy_set_header,Fiber 在路由中直接读取该头做接口级幂等控制。

EarlyData 不是 Fiber 的中间件,而是 TLS 层特性
Fiber 没有、也不需要专门的 EarlyData 中间件。TLS 1.3 的 0-RTT(即 ssl_early_data)在传输层完成,Fiber 作为应用层 HTTP 框架,**收不到原始 ClientHello 扩展,也无法主动触发 early data 发送**。它只能被动接收 Nginx 或其他反向代理透传过来的标识。
Nginx 必须先正确透传 Early-Data 头
若你用 Nginx 做 TLS 终结,Fiber 是后端应用,以下配置缺一不可:
-
ssl_early_data on;必须写在具体server块内(不能放http全局) -
ssl_protocols TLSv1.2 TLSv1.3;—— 只写TLSv1.3会断掉老客户端 -
ssl_session_cache shared:SSL:10m; ssl_session_timeout 4h;—— 否则 PSK 无法复用,0-RTT 直接失效 -
proxy_set_header Early-Data $ssl_early_data;—— 这才是 Fiber 能拿到标识的唯一来源
漏掉 proxy_set_header,Fiber 就永远收不到 Early-Data: 1,后续所有逻辑都无从谈起。
Fiber 中检查 Early-Data 并做幂等性控制
你在 Fiber 路由里直接读请求头即可,不需要额外中间件:
app.Get("/api/status", func(c *fiber.Ctx) error {
early := c.Get("Early-Data")
if early == "1" {
// 允许:只读、幂等操作
return c.JSON(fiber.Map{"status": "ok", "from": "0-RTT"})
}
// 非 0-RTT 路径,可执行登录、提交等操作
return c.JSON(fiber.Map{"status": "ok", "from": "1-RTT"})
})
- 不要对
Early-Data: 1请求做任何写数据库、发消息、扣款等副作用操作 - 敏感接口建议返回
425 Too Early:c.Status(fiber.StatusTooEarly).SendString("retry with full handshake") - 注意:Fiber 默认不自动处理 425 的重试,前端需自行判断 header 并重发
为什么不用自定义中间件封装 Early-Data 判断?
因为它的语义不是“通用前置逻辑”,而是**按接口粒度决策**:
- GET /static/logo.png → 可走 0-RTT
- POST /login → 必须拒绝 0-RTT,无论是否加中间件
- 同一个路由可能因 method 不同而行为不同(如 PUT vs GET)
强行抽成中间件反而模糊了业务边界,还容易误判。直接在 handler 里用 c.Get("Early-Data") 更轻、更可控、更不易漏。
真正容易被忽略的是:Nginx 和 OpenSSL 版本必须严格匹配,且 openssl ciphers -v 'TLSv1.3' 要能列出至少三条原生套件——否则即使配置全对,Early-Data 头也永远不会出现。


















