常见坑
每一章对着一个报错或者一个现象:先用一个最小的程序把它复现出来(编译错误引用 rustc 1.99.0 的原文),再到源码里找它是在哪一行产生的,最后给出修法,修法也跑一遍。机制本身在前面的章节讲过的,这里只链过去,不再重复。
- the trait bound
fn(...) {handler}: Handler<_, _>is not satisfied:future 不是Send、body 提取器不在最后、超过 16 个参数、返回值没实现IntoResponse、参数不是提取器,五种原因同一句话;#[debug_handler]在 debug 构建里逐条说出是哪一种。 - Path segments must not start with
:与 Invalid route、Overlapping method route:0.7 的/:id写法、matchit 判定的冲突、同一方法注册两次,都在构造Router时 panic;without_v07_checks会把/:id当成字面量。 - Expected request with
Content-Type: application/json与 400 / 422:curl -d和只传字符串的fetch都拿到 415;空 body 是 400,字段对不上是 422;Option<Json<T>>会把没带头的 JSON 静默当成None。 - Failed to buffer the request body: length limit exceeded:默认 2 MiB,读到上限才拒绝;回完 413 就关连接,大上传的客户端可能只看到 reset;
DefaultBodyLimit只套在已经存在的路由上。 - expected
Router, foundRouter<AppState>:忘了with_state、with_state写在route前面、返回类型写错,报在nest、get(handler)、oneshot等不同位置。 - 中间件没生效:
.layer之后加的路由不受影响、route_layer与 404 / 405、执行顺序、Handler::layer每个请求重新套一次。 /foo/返回 404:/foo和/foo/是两个路由。- tower 中间件的 BoxError 套不上 Router:
Router::layer要求错误类型是Infallible,会出错的 tower 中间件要先经过HandleErrorLayer。 Option<Query<T>>编译不过:0.8 正式版前去掉了Query的OptionalFromRequestParts实现。(StatusCode, Json)序列化失败仍返回你给的状态码:元组最后设状态码,盖掉了Json自己的 500;修复不在 0.8.9 里。
flowchart TB build["装配主线:编译期"] --> p1["1 Handler 不满足"] build --> p5["5 状态类型对不上"] build --> p8["8 BoxError"] build --> p9["9 Option Query"] boot["装配主线:启动时"] --> p2["2 路由 panic"] boot --> p6["6 中间件没生效"] req["请求主线"] --> p3["3 Json 415、400、422"] req --> p4["4 413"] req --> p7["7 尾斜杠 404"] req --> p10["10 状态码盖掉 500"] p9 --> p1 p6 --> p4
1、5、8、9 是编译错误,2 在启动时 panic;其余几个程序照常运行,要等请求来了才看得出不对,6 的原因却出在装配时 .layer 的位置上。图里两条额外的线:第 9 个在编译器眼里就是第 1 个(报的也是 Handler<_, _> 不满足);第 6 个的规则也是第 4 个里「加了 DefaultBodyLimit::max 还是 413」的原因。读之前最好先读过 Handler trait、FromRequestParts 与 FromRequest 和 layer 与 route_layer。
💬 关联讨论
发起讨论加载中...