发请求
client.get(url).json(&x).send().await 这一行,在连接建立之前经过三段代码:RequestBuilder 把方法、URL、头和 body 攒成一个 Request,途中的任何错误都先存着;Client::execute_request 补上默认头,把请求同步地送进 ClientBuilder::build 组装好的 tower 栈,返回一个 Pending;body 的形态决定 hyper 最后在线上写 Content-Length 还是 chunked。这一部分是请求主线的前半段,后半段(连接从哪来)在 连接,响应在 响应与策略。
代码分布(tag v0.13.5,.rs 行数含测试):src/async_impl/request.rs 1151 行,src/async_impl/client.rs 3196 行(这一部分只读 execute_request、Pending 和 build 的结尾),src/async_impl/body.rs 486 行,src/async_impl/multipart.rs 754 行。实验程序在 exp-reqwest/req-lab,用一个直接读 TCP 字节的 HTTP/1.1 服务器看线上的请求原文。
- 请求构建:
RequestBuilder存的是crate::Result<Request>,非法头、序列化失败都记成builder error,到send才报;header追加、headers替换、json不覆盖已有Content-Type;URL 里的用户名密码变成 basic 认证头;0.13 起query()/form()要开 feature;流式 body 不能try_clone。 - 执行与 Pending:
execute_request只查 scheme、补默认头(默认没有User-Agent)、转Uri;Accept-Encoding和 cookie 由层加;栈从外到里是Decompression、FollowRedirect、CookieService、Retry、HyperService;连接在第一次 poll 时才建,总超时却从send()起算。 - 请求体与 multipart:
Body是完整的Bytes或装箱的流,hyper 按size_hint选分帧;HTTP/1.1 下GET的流式 body 被静默丢弃;multipart::Form的 67 字符边界和预先算出的Content-Length,长度报错的两种后果。
flowchart TB rb["RequestBuilder"] --> send["send"] send --> exec["execute_request"] exec --> stack["tower 栈"] exec --> pend["Pending"] pend --> stack stack --> hyper["legacy Client"] hyper --> enc["hyper 编码 body"] body["Body"] --> rb form["multipart Form"] --> body
💬 关联讨论
发起讨论加载中...