改请求
这一部分的模块都很小,核心逻辑往往只有几行:在 call 时改一下请求(加头、改 URI、放扩展、换 body 类型),或者在响应 future 完成时改一下状态码和头。它们不碰 body 里的数据,所以没有自己的 body 类型。难的不是单个模块,而是它们和别的层的先后:同一个层放在另一个层里面还是外面,结果可能完全不同。
- set_header 一族:
MakeHeaderValue接固定值或闭包;三种模式共用一个apply;请求侧闭包的状态跟着服务实例累积,响应侧每个请求从克隆起步;0.6.11 的多头版本装箱,Clone分两个版本才修全。 - 搬运请求标识与头:客户端带来的
x-request-id原样采用;PropagateRequestId在call时读请求头,必须放在SetRequestId里面,反了的话生成的 id 回不到响应里;SetSensitiveHeaders只打标记,请求侧要放在Trace外面。 - 小型改写层:
NormalizePath只改 URI 不重定向,顺手把开头的多个斜杠并成一个;append_trailing_slash会让 0.7.0 的ServeDir对文件回 404;SetStatus不看内层给了什么。 - 校验与鉴权:
AcceptHeader不看 q 值,has_header_value只看第一个值;弃用的bearer按字节比较;AddAuthorization默认不标敏感;AsyncRequireAuthorization在整个鉴权期间占着内层的就绪名额。
flowchart TB
req[请求] --> c1["call 时:改请求"]
c1 --> sh["SetRequestHeader、SetRequestId、AddExtension"]
c1 --> rw["NormalizePath、MapRequestBody"]
c1 --> mark["SetSensitiveRequestHeaders、AddAuthorization"]
c1 --> gate{"ValidateRequestHeader"}
gate -->|拒绝| short[短路:401 / 403 / 406]
gate -->|放行| inner[内层]
inner --> c2["响应 future 完成时:改响应头和状态码"]
c2 --> rs["SetResponseHeader、PropagateRequestId、PropagateHeader、SetStatus、MapResponseBody"]
贯穿四章的一条规律:请求侧的层在 call 里直接用 &mut self 上的配置,响应侧的层要把配置克隆进 future,因为 future 比 &mut self 的借用活得久。SetResponseHeader、MapResponseBody 比它们的请求侧版本多一个 Clone 约束,带状态的闭包放在两侧行为不同,都是这个原因。
💬 关联讨论
发起讨论加载中...