【免费下载链接】wreq
An ergonomic, privacy-aware Rust HTTP Client
wreq 是一个注重易用性与隐私的 Rust 异步 HTTP 客户端。在 wreq 中取消请求的方式非常统一:丢弃(drop)try_send_request返回的请求 future 即可。但不同协议下,这次取消真正"做到"的事情完全不同——这就是cancel safety(取消安全性)的核心差异。
本文带你 3 分钟搞懂:wreq 中取消请求的底层机制、HTTP/1、HTTP/2、HTTP/3 三种协议的取消行为差异,以及让取消真正生效的实操要点。🎯
先搞懂统一模型:丢弃 future = 取消请求
wreq 对三个协议采用同一个取消入口,官方文档把它称为 "Cancel safety":
请求 future 支持取消:在 future 完成前 drop 它,就是取消该操作的标准方式。协议决定这次取消在网络上实际做什么。
- 请求被取消后,仍在排队的请求会得到
TrySendError(定义见 dispatch.rs); - 连接上后续发出的请求会返回canceled 错误,可以用
Error::is_canceled判断,错误信息显示为"operation was canceled"。
完整说明见模块级文档:lib.rs。
一张表看懂三大协议的取消差异
| 协议 | 取消时在网络上做什么 | 连接能否复用 | 影响范围 |
|---|---|---|---|
| HTTP/1 | 关闭底层 I/O(协议无单请求中止机制) | ❌ 不能 | 整条连接 |
| HTTP/2 | 发送RST_STREAM(CANCEL错误码) | ✅ 可以 | 仅单条流 |
| HTTP/3 | 用H3_REQUEST_CANCELLED取消未完成的发送/接收方向 | ✅ 可以 | 仅单个请求 |
HTTP/1 取消:整条连接"陪葬" ⚠️
HTTP/1 的响应是按顺序串行写在同一条连接上的,协议本身没有"只中止第 N 个请求"的手段。所以 wreq 的处理是:
- 你 drop 掉 in-flight 的请求 future;
- 连接驱动器观察到取消后关闭底层 I/O;
- 同一个
SendRequest上后续所有调用都会返回canceled错误——连接不可复用,需要重建连接。
相关行为文档:conn/http1.rs。
新手提示:如果你用 HTTP/1 实现超时取消,要预期连接会被断开,别指望取消后还能继续用这条连接发下一个请求。
HTTP/2 取消:RST_STREAM 精准重置单条流 ✅
HTTP/2 是多路复用的:一条连接上有许多独立的"流"(stream),取消可以精准到流。
wreq 的做法是:若请求流已打开,取消时会发送RST_STREAM帧并携带CANCEL错误码(对应 RFC 9113 §7),通知对端停止处理这条流——而不是继续传输一个反正会被丢弃的响应体。重置帧由后台任务在驱动时发出,共享连接对其它在途及后续请求完全不受影响。
核心实现:检测到客户端取消后发送重置,见 proto/http2/client.rs;行为文档见 conn/http2.rs。
HTTP/3 取消:双向取消,连接继续可用 🚀
HTTP/3 建立在 QUIC 之上,同样多路复用。wreq 的取消分两种情况:
- 响应头交付前取消:请求 future 未完成就被 drop,会取消该请求未完成的发送方向和接收方向,QUIC 层使用
H3_REQUEST_CANCELLED错误码(对应 RFC 9114 §4.1.1),共享连接保持可用; - 响应头交付后取消:此时丢弃响应体只会取消"接收"方向;若请求体还没发完,发送工作会继续独立进行,不受影响。
关键实现:发送/接收守护对象的Drop分别调用stop_stream/stop_sending发出H3_REQUEST_CANCELLED,见 proto/http3/client.rs;行为文档见 conn/http3.rs。
实操要点:让取消真正生效的 3 步 📌
第 1 步:用"丢弃"表达取消。典型做法是配合tokio::time::timeout——超时时超时逻辑会 drop 内部 future,取消自动生效:
// 5 秒超时,超时后 future 被 drop,请求即被取消 let res = tokio::time::timeout(Duration::from_secs(5), tx.try_send_request(req)).await;第 2 步:保持驱动连接和后台任务。无论哪种协议,取消信号(如RST_STREAM)都需要连接驱动继续运行才能送达对端。drop 请求 future 后,请继续spawn并 poll 那个Connectionfuture,直到它完成——三个协议的文档都特别强调了这一点("Keep driving the connection and its background tasks")。
第 3 步:按协议预期处理错误。
- HTTP/1:连接已关闭,为下一个请求新建连接;
- HTTP/2 / HTTP/3:连接继续可用,直接复用
SendRequest; - 用
Error::is_canceled区分"取消导致"的错误与真正的网络错误,便于做差异化重试。
小结
- 在 wreq 中取消请求 =drop 请求 future,入口统一、心智负担低;
- HTTP/1取消代价最大:整条连接关闭,不可复用;
- HTTP/2取消最精准:
RST_STREAM(CANCEL)只重置单条流; - HTTP/3取消最细粒度:双向独立取消,
H3_REQUEST_CANCELLED,连接持续可用; - 无论哪种协议:取消后继续驱动连接,才能把取消通知送达对端。
选对协议 + 正确 drop + 保持连接驱动,你的 wreq 客户端就能做到又快又安全的请求取消。✨
【免费下载链接】wreq
An ergonomic, privacy-aware Rust HTTP Client
相关推荐
终极指南:让老旧Mac重获新生,免费升级最新macOS系统
终极指南:让老旧Mac重获新生,免费升级最新macOS系统 你是否有一台被苹果官方抛弃的老款Mac,却渴望体验最新的macOS功能?OpenCore Legac
操作系统固件驱动开发xlwings实际应用案例:从金融分析到数据可视化的完整解决方案
xlwings实际应用案例:从金融分析到数据可视化的完整解决方案 xlwings是一个强大的Python库,它让Excel与Python的无缝集成成为可能,为金
后端HTTP请求取消机制:async-http-client Future.cancel()应用指南
HTTP请求取消机制:async http client Future.cancel 应用指南 在现代异步HTTP客户端开发中, 请求取消机制 是提升应用性能和
后端网络
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考