常见坑
每一章对着一个报错或现象:先用最小的程序复现(编译错误和警告引用 rustc 1.99.0 的原文,运行结果都跑过 3 次),再找到它在源码哪一行产生,最后给出修法。机制本身在前面的模块页讲过的,这里只链过去;能换个角度复现的(真实 TCP 连接、真实的反向代理、放进 axum),就换个角度。
- Invalid CORS configuration: Cannot combine ...
Access-Control-Allow-Headers: *:permissive()加凭据,在Router::layer时 panic,先撞上的是请求头那一条;开发用very_permissive()。 - there are extra bytes after body has been decompressed:上游发了两段 gzip,第二段单独成帧时报错,同帧时静默截断;reqwest 0.12 里显示为
error decoding response body。 - 限了 1 MiB,handler 还是读到了 10 MiB:限额在解压外面;照文档关掉 axum 的
DefaultBodyLimit反而拆掉了数解压后字节的那道防线。 - 307 Temporary Redirect 原样回到调用方:
Standard不复制非空 body;Limited用完也是返回 3xx 而不是报错。 ifandelsehave incompatible types:同样的层换个顺序,响应 body 类型就变;装箱前先用MapResponseBodyLayer统一。- 日志里还是有 authorization:标记层在
Trace里面不起作用;合一的SetSensitiveHeadersLayer总会漏一侧。 - NormalizePath 之后目录无限 307,文件 404:去尾斜杠和
ServeDir的目录跳转互相抵消;加尾斜杠撞上 0.7 的 #678;nest_service下的跳转丢前缀。 - use of deprecated ...: too basic to be useful in real applications:
bearer/basic和TimeoutLayer::new的弃用与替代。 - ServeDir 回 500,日志里什么都没有:日志挂在隐式的
tracingfeature 上;权限不足是 404,文件名过长是 500。 - 反向代理后面 CsrfLayer 回 403:代理改写
Host,不带Sec-Fetch-Site的请求被判跨源;X-Forwarded-Host不参与。 - 在途请求数只增不减:客户端断开时计数立刻回落;下不来的是开着的长连接。
flowchart TB build["编译期"] --> p5["5 类型不匹配"] build --> p8["8 弃用警告"] boot["装配时"] --> p1["1 CORS panic"] deploy["部署与依赖"] --> p9["9 ServeDir 没日志"] deploy --> p10["10 代理后 403"] req["请求时:顺序"] --> p3["3 限额被绕过"] req --> p6["6 日志里的 token"] req --> p7["7 NormalizePath 与 ServeDir"] req --> p4["4 307 原样返回"] body["body 流动时"] --> p2["2 多余字节"] body --> p11["11 在途数"] p3 --> p5
3、5 之间那条线:想用开关在两种顺序之间切换,就会从第 3 个坑走进第 5 个。3、6、7 都是同一类问题:层的相对位置决定了谁先看到请求、谁后看到响应,而编译器不会提醒。
已在别处成文的
下面几个也常见,已经有完整的复现,只列链接:
| 现象 | 在哪里 |
|---|---|
CorsLayer 放在 TraceLayer 外面编译不过(内层 body 没有 Default) | 四件套 的「Default 让层的顺序影响编译」 |
客户端栈里 TimeoutLayer 套不上 hyper 的 Incoming | 拼一个客户端栈 |
鉴权头放在 FollowRedirect 里面,跨源跳转后 token 照发 | 拼一个客户端栈 的「鉴权:要在 FollowRedirect 外面」 |
ServiceBuilderExt 和 ServiceExt 一起导入报 E0034 | ServiceBuilderExt 与 ServiceExt |
CompressionLayer 在 body 结尾 panic(#732) | axum 卷 压缩 |
Accept-Encoding: identity;q=0 拿到 406(0.7.0 的 #693) | axum 卷 压缩 |
Content-Encoding: GZIP 不解压 | reqwest 卷 GZIP 不解压,identity 挡不住解压 |
重定向以后 Authorization 没了 | reqwest 卷 重定向以后 Authorization 没了,x-api-key 还在 |
NormalizePathLayer 挂在 Router::layer 上不生效 | axum 卷 /foo/ 返回 404 |
💬 关联讨论
发起讨论加载中...