Rust in Everything
基于 tower-http 0.7.1

常见坑

每一章对着一个报错或现象:先用最小的程序复现(编译错误和警告引用 rustc 1.99.0 的原文,运行结果都跑过 3 次),再找到它在源码哪一行产生,最后给出修法。机制本身在前面的模块页讲过的,这里只链过去;能换个角度复现的(真实 TCP 连接、真实的反向代理、放进 axum),就换个角度。

  1. Invalid CORS configuration: Cannot combine ... Access-Control-Allow-Headers: *:permissive() 加凭据,在 Router::layer 时 panic,先撞上的是请求头那一条;开发用 very_permissive()。
  2. there are extra bytes after body has been decompressed:上游发了两段 gzip,第二段单独成帧时报错,同帧时静默截断;reqwest 0.12 里显示为 error decoding response body。
  3. 限了 1 MiB,handler 还是读到了 10 MiB:限额在解压外面;照文档关掉 axum 的 DefaultBodyLimit 反而拆掉了数解压后字节的那道防线。
  4. 307 Temporary Redirect 原样回到调用方:Standard 不复制非空 body;Limited 用完也是返回 3xx 而不是报错。
  5. if and else have incompatible types:同样的层换个顺序,响应 body 类型就变;装箱前先用 MapResponseBodyLayer 统一。
  6. 日志里还是有 authorization:标记层在 Trace 里面不起作用;合一的 SetSensitiveHeadersLayer 总会漏一侧。
  7. NormalizePath 之后目录无限 307,文件 404:去尾斜杠和 ServeDir 的目录跳转互相抵消;加尾斜杠撞上 0.7 的 #678;nest_service 下的跳转丢前缀。
  8. use of deprecated ...: too basic to be useful in real applications:bearer / basic 和 TimeoutLayer::new 的弃用与替代。
  9. ServeDir 回 500,日志里什么都没有:日志挂在隐式的 tracing feature 上;权限不足是 404,文件名过长是 500。
  10. 反向代理后面 CsrfLayer 回 403:代理改写 Host,不带 Sec-Fetch-Site 的请求被判跨源;X-Forwarded-Host 不参与。
  11. 在途请求数只增不减:客户端断开时计数立刻回落;下不来的是开着的长连接。
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 一起导入报 E0034ServiceBuilderExt 与 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

💬 关联讨论

发起讨论
加载中...