news 2026/10/15 18:28:34

如何安全取消 wreq 请求?深入 HTTP/1、HTTP/2、HTTP/3 的 Cancel Safety 完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何安全取消 wreq 请求?深入 HTTP/1、HTTP/2、HTTP/3 的 Cancel Safety 完整指南

【免费下载链接】wreq

An ergonomic, privacy-aware Rust HTTP Client

项目地址:https://gitcode.com/gh_mirrors/rq/wreq
点击查看免费下载

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 的处理是:

  1. 你 drop 掉 in-flight 的请求 future;
  2. 连接驱动器观察到取消后关闭底层 I/O;
  3. 同一个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

项目地址:https://gitcode.com/gh_mirrors/rq/wreq
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 18:25:42

MT4 API 开发实战:行情、订单与账户接口对接指南

简介:这份资源是面向外汇量化开发者与MT4平台二次开发人员的完整API开发文档包,重点解决DataFeedAPI、ManagerAPI与ReportAPI三大接口在插件、EA及数据集成场景中的落地问题。包内共463个文件,以164个C头文件与160个cpp源码为主体&#xff0c…

作者头像 李华
网站建设 2026/10/15 18:25:38

ARM编译器5.06实战:从armcc环境配置到避坑技巧全解析

简介:面向嵌入式硬件开发者的ARM Compiler 5.06离线安装包,用于在Keil MDK等图形化IDE中补齐ARMCC工具链,解决Cortex-A/R/M系列处理器从编译、汇编到链接的完整构建需求。资源共3个文件,包含可执行的安装程序(exe&…

作者头像 李华
网站建设 2026/10/15 18:23:54

CangjieCorpus 语料库架构解析:面向 RAG 的仓颉编程语言知识基座

文档知识库教程OpenHarmony 【免费下载链接】CangjieCorpus 本仓库为仓颉编程语言语料库,聚焦 仓颉编程语言 核心知识体系,整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源,经结构化处理与专业标注,构建为支持 R…

作者头像 李华