Handler 与提取器
这是本卷的重点。axum 没有路由宏,处理函数就是 async fn,它的每个参数都是一个「提取器」:一个能从请求里构造出自己的类型。函数能被 get(...) 接受,靠的是 Handler trait 对 1–16 个参数的函数的宏实现;每个参数怎么从请求里来,靠的是 axum-core 的两个提取器 trait。常见坑里一半的编译错误都出在这一部分。
前两章讲机制,后三章讲具体的提取器:
- Handler trait:
Handler<T, S>的T是参数类型的元组,用来绕开一致性规则;impl_handler!经all_the_tuples!展开出 1–16 个参数的 impl,call从左到右跑提取器,任何一个失败就返回 rejection;HandlerService把 handler 和状态包成 towerService。 - FromRequestParts 与 FromRequest:前者借
&mut Parts、可以有多个,后者拿走整个请求、只能放最后,所以 body 只会被读一次;ViaParts标记让只看头的提取器也能放最后;0.8 起Option<T>要求OptionalFromRequestParts,不再吞掉所有错误。 - State 与 FromRef:
Router<S>的S是还欠着的状态类型,with_state之后变成Router<()>;FromRef从总状态里取出子状态;State在编译期检查,Extension在运行时查找。 - Path、Query 与请求元数据:
Path用自己的 serdeDeserializer读 matchit 抓到的参数,Query用serde_urlencoded;错误怎么分类、回什么状态码;MatchedPath、OriginalUri、ConnectInfo这些元数据从哪来。 - body 提取器:
Json、Form、Bytes、String、Multipart怎么读 body;DefaultBodyLimit的 2 MB 默认上限在哪里生效;各种 rejection 对应的 400 / 413 / 415 / 422。
flowchart TB fnitem["async fn 处理函数"] --> handler["Handler trait"] handler --> parts["FromRequestParts:前面的参数"] handler --> whole["FromRequest:最后一个参数"] parts --> st["State"] parts --> pq["Path、Query、元数据"] whole --> bodyx["Json、Form、Bytes 等"] whole -.->|"ViaParts"| parts
Handler 决定参数按什么顺序、以什么身份被提取;两个提取器 trait 决定每个参数能看到请求的哪一部分;后三章是这两个 trait 的具体实现。返回值那一侧的 IntoResponse 在下一部分的 IntoResponse 与 IntoResponseParts。
💬 关联讨论
发起讨论加载中...