ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

axum-core 0.5 演进全解析:从请求提取、响应构建到未知大小请求体(Body::unknown)的完整指南

axum-core 0.5 演进全解析:从请求提取、响应构建到未知大小请求体(Body::unknown)的完整指南 axum-core 0.5 演进全解析从请求提取、响应构建到未知大小请求体Body::unknown的完整指南【免费下载链接】axumHTTP routing and request-handling library for Rust that focuses on ergonomics and modularity项目地址: https://gitcode.com/GitHub_Trending/ax/axum导读axum-core是 axum Web 框架的核心底层 crate它不包含路由与请求分发逻辑而是定义了提取器extractor、响应构建response building、请求体body等一切上层 API 赖以运行的基础类型与 trait。本文以 axum-core/CHANGELOG.md 为骨架逐版本梳理其关键演进脉络并结合 axum-core/src 下的真实源码深入讲解Body::unknown、DefaultBodyLimit、IntoResponseParts、OptionalFromRequest等核心机制的底层实现。读完本文你将掌握如何用未知大小请求体优雅响应 HEAD 请求、如何为单个路由定制请求体大小上限、如何通过IntoResponseParts构建可组合的响应类型以及这些能力在 axum 0.4 → 0.5 演进中经历了怎样的破坏性变更与设计取舍。一、axum-core 是什么axum-core是 axum 工作区中的基础 crate官方描述为 Core types and traits for axum。它的定位非常明确库作者在实现FromRequest或IntoResponse时应当优先依赖axum-core而不是axum本身见 axum-core/src/lib.rs从而避免在提供自定义提取器或响应类型时引入整个 axum 路由层的依赖。从 axum-core/Cargo.toml 可以看到它的依赖面刻意保持精简bytes、http、http-body、http-body-util、futures-core、tower-layer、tower-service、pin-project-lite、sync_wrapper、mime可选 feature 仅有tracing与用于文档链接解析的__private_docs。axum本身则是一个更厚的封装层它基于axum-core的能力构建路由、中间件与高层提取器。在 axum-core/src/lib.rs 中axum-core对外暴露三大模块也是本文后续要逐一展开的主题axum_core::body请求/响应使用的请求体类型Body与相关流式工具axum_core::extract提取器 traitFromRequest/FromRequestParts以及DefaultBodyLimit、OptionalFromRequest等配套类型axum_core::response响应构建 traitIntoResponse/IntoResponseParts、ResponseParts、AppendHeaders、ErrorResponse等。另外还定义了统一错误类型Error见 axum-core/src/error.rs它包装BoxError并提供into_inner无损转换。二、最新开发版Unreleased三个值得关注的变化axum-core/CHANGELOG.md的 Unreleased 区段记录了三项最新变更其中两项是全新能力一项是行为修正2.1ResponseParts::status与status_mut让 IntoResponseParts 实现者可以设置响应状态码新增ResponseParts::status与ResponseParts::status_mut访问器允许IntoResponseParts的实现者在向响应追加头部/扩展的同时修改响应状态码对应 PR [#3721]。在源码 axum-core/src/response/into_response_parts.rs 中ResponseParts是一个持有Response的薄封装此前只暴露headers/headers_mut/extensions/extensions_mut四组访问器pub struct ResponseParts { pub(crate) res: Response, } impl ResponseParts { pub fn status(self) - StatusCode { self.res.status() } pub fn status_mut(mut self) - mut StatusCode { self.res.status_mut() } pub fn headers(self) - HeaderMap { self.res.headers() } pub fn headers_mut(mut self) - mut HeaderMap { self.res.headers_mut() } pub fn extensions(self) - Extensions { self.res.extensions() } pub fn extensions_mut(mut self) - mut Extensions { self.res.extensions_mut() } }新增的status/status_mut补齐了最后一块拼图使IntoResponseParts的实现可以在into_response_parts(self, mut res: ResponseParts)中直接改写状态码例如把某个响应强制标记为204 No Content或202 Accepted而不必依赖外层元组的StatusCode元素。由此IntoResponseParts的职责从只能加头加扩展扩展为可以完整定制响应部件。2.2Body::unknown建模未知大小的请求体新增Body::unknown用于建模未知大小的请求体在处理HEAD请求时尤其有用对应 PR [#3742]。这是本文后续章节将重点展开的机制。其配套实现位于 axum-core/src/body/unknown.rs是一个零分配、Copy、Default的内部类型UnknownD。2.3impl IntoResponse for ()现在返回未知大小请求体变更impl IntoResponse for ()它会被impl IntoResponse for HeaderMap、impl IntoResponse for Extensions等调用现在返回一个大小未知的请求体而非此前的大小为 0 的空请求体。在 axum-core/src/response/into_response.rs 中可以确认这一变化impl IntoResponse for () { fn into_response(self) - Response { Body::unknown().into_response() } }而HeaderMap、Extensions等类型的IntoResponse实现同文件 L342-L356正是通过().into_response()获得一个基础响应再填充头部/扩展因此它们产出的响应体也随之变为未知大小。2.4 修复BytesMut 提取器忽略自定义请求体中的非数据帧修复让BytesMut提取器忽略来自自定义请求体的非数据帧如 trailer 帧与Bytes提取器的行为保持一致对应 PR [#3811]。这是一个一致性修正在使用自定义http_body::Body作为请求体来源时body 中可能混入 trailer 等非数据帧Bytes提取器会跳过它们只收集数据帧而此前BytesMut提取器可能存在行为差异本修复统一了两者的语义。三、Body::unknown 深度剖析未知大小请求体的底层实现与 HEAD 响应实战3.1 为什么需要未知大小的请求体HTTP 响应体在语义上通常带有一个大小提示size hint。在 axum 的Body类型中axum-core/src/body.rspub struct Body(BoxBody);它实现了http_body::Bodytrait同文件 L140-L161通过size_hint()向上层hyper 等 HTTP 服务端报告 body 的长度信息。Body::unknown()与Body::empty()最本质的区别正在于size_hint的上界Body::empty()size_hint上界为 0 字节Body::unknown()size_hint没有上界。而除此之外未知大小的 body 表现得和空 body 完全一致is_end_stream()返回true被poll_frame轮询时立即返回Poll::Ready(None)即立即结束流。为什么这一点对HEAD请求如此重要RFC 9110Section 9.3.2指出服务端响应HEAD请求时可以返回与对应GET请求相同的头部包括Content-Length但不允许发送响应体。由于HEAD响应看起来应该有内容却又不能有内容此时如果使用空 body其 0 字节的大小上界会与头部声明的预期长度产生语义冲突而使用未知大小的 body则既不需要真正计算/传输昂贵的GET响应体又能向客户端与中间层表达长度未知、流已结束的正确语义。3.2 内部实现一个零分配的空壳类型Body::unknown()的内部实现axum-core/src/body/unknown.rs非常精巧——它是一个不持有任何数据的零大小类型pub(crate) struct UnknownD { _marker: PhantomDatafn() - D, } implD: Buf Body for UnknownD { type Data D; type Error Infallible; fn poll_frame( self: Pinmut Self, _cx: mut Context_, ) - PollOptionResultFrameSelf::Data, Self::Error { Poll::Ready(None) // 立即结束 } fn is_end_stream(self) - bool { true // 流已结束 } fn size_hint(self) - SizeHint { SizeHint::default() // 上界为 None即未知 } }几个值得注意的实现细节UnknownD通过PhantomDatafn() - D只保留类型参数痕迹不占用任何运行时内存并且实现了Default、Clone、Copy可以零成本地任意传递Error类型是Infallible因为一个立即结束的 body 永远不会产生错误size_hint()返回SizeHint::default()其下界为 0、上界为None这正是未知大小语义的落点该类型是pub(crate)的内部实现外部只能通过Body::unknown()这个公开入口使用。3.3 实战用 Body::unknown 响应 HEAD 请求在 axum 中路由层面通常已经帮你处理了HEADaxum 对每个GET路由自动提供HEAD支持参见 routing/tests/get_to_head.rs。当你在自定义响应逻辑中需要主动构造一个长度未知、无内容的响应时可以这样使用use axum::{response::{IntoResponse, Response}, body::Body}; async fn head_handler() - Response { // 头部声明了与 GET 一致的 Content-Length // 但 body 既不需要计算也不需要传输 let mut res Body::unknown().into_response(); res.headers_mut() .insert(content-length, 12345.parse().unwrap()); res }更常见的情形是一个路由同时处理GET与HEADHEAD时跳过昂贵的大数据体构造直接返回Body::unknown()use axum::{routing::get, Router, response::IntoResponse, body::Body}; use http::{Method, Request}; async fn data_handler(req: RequestBody) - Response { if req.method() Method::HEAD { return Body::unknown().into_response(); } // 正常 GET构造昂贵的响应体 huge_payload().into_response() } let app Router::new().route(/data, get(data_handler));由于impl IntoResponse for Bodyinto_response.rs直接可用Body::unknown()可以像任何响应类型一样直接返回。3.4 Body 的其他构造方式速览axum_core::body::Body是 axum 请求与响应的默认 body 类型axum::body::Body即其 re-export。除unknown()外body.rs 还提供Body::new(body)包装任意http_body::BodyBody::empty()空 bodysize_hint上界为 0Body::from_stream(stream)从TryStream构造流式 body内部经SyncWrapper包装以便跨线程Body::into_data_stream()反向将 body 转为BodyDataStream丢弃 trailer 等非数据帧大量From实现String、static str、Vecu8、Bytes、static [u8]、Cow等body.rs其中From()是 0.4.2 引入的见下文版本史。BodyDataStream还实现了Stream::size_hint0.5.2 的变更见下文将内部 body 的SizeHint转换为标准的(usize, Optionusize)元组形式body.rs。四、请求体大小限制DefaultBodyLimit 的演进与实战配置4.1 安全默认值2 MB 上限的由来DefaultBodyLimit是 axum-core 提供的请求体大小限制机制。其文档明确指出axum-core/src/extract/default_body_limit.rs出于安全原因Bytes默认不会接受超过 2MB 的请求体这同样适用于内部使用Bytes的提取器如String、Json、Form。这个默认值源于 0.3.0-rc.2 的破坏性变更对应 PR [#1346]在此之前Bytes::from_request会尝试读取整个请求体而不检查长度恶意对端只要发送超大甚至无限的请求体服务器就可能耗尽内存而崩溃。该变更同时覆盖了内部复用Bytes的String提取器。4.2 三种配置入口DefaultBodyLimit提供三个公开方法default_body_limit.rs方法签名作用DefaultBodyLimit::max(limit)const fn max(limit: usize) - Self将默认 2MB 限制替换为自定义大小单位字节DefaultBodyLimit::disable()const fn disable() - Self完全禁用默认限制DefaultBodyLimit::apply(mut Request)fn applyB(self, req: mut RequestB)在提取器内部针对单个请求动态应用限制其内部通过枚举DefaultBodyLimitKind { Disable, Limit(usize) }表达限制状态default_body_limit.rs并且DefaultBodyLimit自身派生Debug, Clone, Copy且带#[must_use]。从实现上看无论是作为 Layer 使用还是调用apply最终都是把DefaultBodyLimitKind写入请求的Extensions中见 default_body_limit.rs 的Layer实现与DefaultBodyLimitService由Bytes等提取器在消费 body 时读取该扩展决定读取上限。4.3 全局修改默认限制use axum::{ Router, routing::post, body::Body, extract::{Request, DefaultBodyLimit}, }; let app Router::new() .route(/, post(|request: Request| async {})) // 把默认 2MB 改为 1KB .layer(DefaultBodyLimit::max(1024));4.4 不同路由使用不同限制DefaultBodyLimit是局部机制它只作用于显式应用它的FromRequest实现或调用其他应用了它的提取器。因此可以把它挂在单个路由上实现每条路由各自的限制use axum::{Router, routing::post, body::Body, extract::{Request, DefaultBodyLimit}}; let app Router::new() // 这条路由限制为 1KB .route(/, post(|request: Request| async {}).layer(DefaultBodyLimit::max(1024))) // 这条路由仍然使用默认 2MB .route(/foo, post(|request: Request| async {}));4.5 在自定义提取器内部动态应用限制DefaultBodyLimit::apply0.5.3 新增对应 PR [#3368]可以在提取器内部针对单个请求修改限制。下面的示例实现了一个最多 1KB的Bytes提取器变体use axum::{ extract::{DefaultBodyLimit, FromRequest, rejection::BytesRejection, Request}, body::Bytes, }; struct Bytes1KB(Bytes); implS: Sync FromRequestS for Bytes1KB { type Rejection BytesRejection; async fn from_request(mut req: Request, _: S) - ResultSelf, Self::Rejection { DefaultBodyLimit::max(1024).apply(mut req); Ok(Self(Bytes::from_request(req, ()).await?)) } }4.6 与 tower-http RequestBodyLimit 的差异DefaultBodyLimit与tower_http::limit::RequestBodyLimit功能相似但机制不同default_body_limit.rsDefaultBodyLimitaxum 侧局部生效只作用于显式应用它的FromRequest实现。如果你依赖第三方提取器它可能不会遵守这个限制。可通过RequestExt::with_limited_body/RequestExt::into_limited_body定义于 axum-core/src/ext_traits/request.rs手动为某个请求应用限制RequestBodyLimittower-http 侧全局生效对所有请求、无论使用什么提取器、如何消费 body 都强制施加限制。官方文档的建议是一般情况下优先使用DefaultBodyLimit但如果使用第三方提取器且希望限制一定生效则应改用RequestBodyLimit。文档中还给出了禁用默认限制 换用 tower-http 全局限制的组合示例use axum::{Router, routing::get, body::{Bytes, Body}, extract::DefaultBodyLimit}; use tower_http::limit::RequestBodyLimitLayer; let app: Router() Router::new() .route(/, get(|body: Bytes| async {})) // 禁用默认限制 .layer(DefaultBodyLimit::disable()) // 换成自定义全局限制10MB .layer(RequestBodyLimitLayer::new(10 * 1000 * 1000));另外需要注意如果提取器直接用Body::poll_frame之类的方式消费 body默认限制不会生效。同时官方也提醒若从不受信任的对端接收数据禁用限制后应自行添加如tower_http::limit之类的防护。4.7 相关历史变更0.4.4DefaultBodyLimit实现CopyDefaultBodyLimit::max与DefaultBodyLimit::disable变为可在 const 上下文使用对应 PR [#2875]0.5.3新增DefaultBodyLimit::apply对应 PR [#3368]限制机制最早于 0.3.0-rc.2 引入对应 PR [#1346]0.2.8 也同步收录了同样的变更说明。五、请求提取 trait 的演进FromRequestParts、OptionalFromRequest 与 RPITIT5.1 提取器体系的两层架构axum-core将请求提取拆成两层 traitaxum-core/src/extract/mod.rspub trait FromRequestPartsS: Sized { type Rejection: IntoResponse; fn from_request_parts(parts: mut Parts, state: S) - impl FutureOutput ResultSelf, Self::Rejection Send; } pub trait FromRequestS, M private::ViaRequest: Sized { type Rejection: IntoResponse; fn from_request(req: Request, state: S) - impl FutureOutput ResultSelf, Self::Rejection Send; }设计要点FromRequestParts只消费http::request::Parts状态码、方法、头部、扩展等不消费请求体因此多个此类提取器可以任意顺序共存于同一 handlerFromRequest消费整个请求含 body在同一 handler 中只能使用一次不需要 body 的提取器应实现FromRequestParts而不是FromRequestFromRequestParts的实现通过自动桥接extract/mod.rs获得FromRequest的能力——先拆出 Parts 再交给from_request_parts两个 trait 都通过#[diagnostic::on_unimplemented]提供友好的编译器错误提示。这套Parts 与 Request 分离的架构是 0.3.0 / 0.4.0 一系列破坏性变更的产物0.3.0 新增FromRequestParts并移除RequestParts与BodyAlreadyExtractedPR [#1272]0.4.0 则让FromRequestParts、FromRequest、RequestExt不再泛型于请求体类型BPR [#1751] 与 [#1789]因为 hyper 1.0 移除了hyper::Bodyaxum 改用自己的axum_core::body::Body。5.2 0.5.0 的破坏性变更Option 提取器与 OptionalFromRequest0.5.0 引入了两项重大破坏性变更1用 return-positionimpl Traitin traitsRPITIT替代#[async_trait]PR [#2308]。从上面的 trait 定义可以看到from_request_parts/from_request直接返回impl Future...不再依赖async_trait宏装箱。这意味着提取器 trait 现在是真 async的调用侧的类型与性能特征都更优。2OptionT提取器行为重构PR [#2475]。此前OptionT作为提取器时T提取失败会被静默转为None。0.5.0 起OptionT作为最后一个提取器使用时要求T: OptionalFromRequestOptionT作为其他位置的提取器使用时要求T: OptionalFromRequestParts这两个新 traitaxum-core/src/extract/option.rs允许T的作者自定义提取失败时返回None还是拒绝的行为。配套实现同文件 L40-L68中impl FromRequestPartsS for OptionT与impl FromRequestS for OptionT都标注了#[diagnostic::do_not_recommend]——当用户错误地对OptionT使用?或unwrap时编译器会给出不要直接对 Option 提取器这样做的提示。这正是 0.5.6 中使用#[diagnostic::do_not_recommend]改善错误信息的延续该属性让OptionT提取器出现编译错误时编译器不再把泛型约束栈顶层的复杂 impl 报给用户而是指向更直观的说明。迁移提示如果你在 0.5.0 之前依赖OptionT提取器升级后需要确认T是否实现了OptionalFromRequest/OptionalFromRequestParts对多数内置类型如HeaderMap、ExtensionT等axum 均已提供对应实现。5.3 Result 提取器extract/mod.rs还提供了ResultT, T::Rejection的提取实现extract/mod.rs无论T实现FromRequestParts还是FromRequest其Result形式都可以作为提取器使用且Rejection为Infallible——提取永远成功失败被包装进Err返回给 handler 自行处理。六、响应构建体系IntoResponse 与 IntoResponseParts 的进化6.1 三大核心类型IntoResponseaxum-core/src/response/into_response.rs可从 handler 直接返回的类型都要实现它其关联的Response类型是ResponseT Body的别名response/mod.rsIntoResponsePartsaxum-core/src/response/into_response_parts.rs为响应追加头部/扩展部件的 trait配合元组返回语法使用ResponsePartsIntoResponseParts::into_response_parts接收并返回的中间类型暴露status/headers/extensions及其_mut版本。6.2 元组返回的宏展开逻辑IntoResponse为任意形如(Parts..., R)的元组提供了实现宏impl_into_responseinto_response.rs其执行顺序是先把最后一个元素R转为响应再依次把前面的各部件通过into_response_parts写入响应。此外还支持(StatusCode, R)用指定的状态码覆盖R产生的默认状态码into_response.rs(R,)单元素元组0.4.0 新增PR [#2143]直接透传(http::response::Parts, R)与(http::response::Response(), R)0.2.4 新增PR [#950]允许用现成的响应 Parts/模板覆盖状态码、头、扩展(Parts | Request(), $(impl IntoResponseParts), impl IntoResponse)0.2.4 新增PR [#980]impl IntoResponseParts for ()0.4.3 新增PR [#2471]空操作部件。IntoResponseParts的内建实现包括HeaderMap、Extensions、[(K, V); N]数组、()以及所有元组形式into_response_parts.rs。此外OptionT在T: IntoResponseParts时也实现了该 trait同文件 L86-L99。注意 0.9 行为变化IntoResponseFailed与ForceStatusCoderesponse/mod.rs 中定义了IntoResponseFailed标记扩展与ForceStatusCode包装类型。自 axum 0.9 起当内层IntoResponseParts/IntoResponse失败并返回错误响应时会插入IntoResponseFailed扩展从而阻止外层(StatusCode, ...)的状态码覆盖避免把 500 错误错误地改写成 201 之类。若确实需要强制覆盖请使用ForceStatusCode。6.3 内置响应类型演进时间线0.1.1axum_core::response::Response作为ResponseBoxBody的简写PR [#590]0.2.0新增IntoResponsePartsPR [#797]HeaderMap提取器不再消费头部而是克隆PR [#698]Extensions不再作为提取器PR [#699]0.2.1RequestParts::extract允许以方法调用方式应用提取器PR [#897]——该方法在 0.3.0 重构后被移除0.2.2新增AppendHeadersPR [#927]用于追加头部而非覆盖0.2.3新增response::ErrorResponse与response::ResultPR [#921]0.2.4IntoResponse与IntoResponseParts支持http::Extensions新增(Parts, R)/(Response(), R)等元组实现PR [#950]、[#975]、[#980]0.3.1内置 rejection 增加body_text与status方法PR [#1612]0.3.2为static [u8; N]与[u8; N]实现IntoResponsePR [#1690]0.4.0(R,)单元素元组实现PR [#2143]0.4.2Body实现From()PR [#2411]0.4.4AppendHeaders派生Clone, Copy并加#[must_use]ErrorResponse、IntoResponse::into_response、IntoResponsePartstrait 方法均加#[must_use]PR [#2776]、[#2846]0.5.0所有define_rejection!()生成的 rejection 的Display实现现在会包含内部错误的Display输出与body_text()输出保持一致PR [#3118]。6.4 AppendHeaders追加而非覆盖AppendHeadersIaxum-core/src/response/append_headers.rs解决一个常见痛点直接返回[(content-type, foobar)]会覆盖已有同名字头而AppendHeaders使用headers_mut().append(...)实现追加。典型场景是set-cookieuse axum::{ response::{AppendHeaders, IntoResponse}, http::header::SET_COOKIE, }; async fn handler() - impl IntoResponse { // 别处已设置的 cookie 头 let set_some_cookies axum::http::HeaderMap::new(); ( set_some_cookies, // 追加两条 set-cookie而不覆盖已有的 AppendHeaders([ (SET_COOKIE, foobar), (SET_COOKIE, bazqux), ]) ) }AppendHeaders要求I: IntoIteratorItem (K, V)其中K: TryIntoHeaderName、V: TryIntoHeaderValue转换失败时返回TryIntoHeaderError并转换为500 INTERNAL_SERVER_ERROR响应append_headers.rs。6.5 ErrorResponse 与 Resultaxum::response::ResultT, E ErrorResponseresponse/mod.rs是一个以IntoResponse类型作为错误类型的Result别名由于任意IntoResponse类型都能From转换成ErrorResponse你可以把多个错误类型各异的Result函数用?串联进同一个 handleruse axum::{response::{IntoResponse, Response, Result}, http::StatusCode}; struct ErrorA; impl IntoResponse for ErrorA { fn into_response(self) - Response { (StatusCode::INTERNAL_SERVER_ERROR, error A).into_response() } } enum ErrorB { SomethingWentWrong } impl IntoResponse for ErrorB { fn into_response(self) - Response { (StatusCode::INTERNAL_SERVER_ERROR, error B).into_response() } } async fn handler() - Resultstatic str { try_a()?; try_b()?; Ok(it worked!) } fn try_a() - Result(), ErrorA { Ok(()) } fn try_b() - Result(), ErrorB { Ok(()) }七、错误处理与 rejection 体系7.1 axum_core::Error 与 BoxErroraxum_core::Erroraxum-core/src/error.rs是 axum 生态统一的 body 错误类型pub struct Error { inner: BoxError } impl Error { pub fn new(error: impl IntoBoxError) - Self { ... } #[must_use] pub fn into_inner(self) - BoxError { self.inner } // 0.3.0-rc.3 新增无额外分配 }它实现了Display透传内部错误与std::error::Errorsource()返回内部错误BoxError定义为Boxdyn std::error::Error Send Synclib.rs。Body::from_stream等场景中所有TryStream::Error: IntoBoxError的流错误最终都会被包装成axum_core::Error见 body.rs 的StreamBody实现。7.2 rejection 的演进0.2.0HeaderMap提取不再移除头部PR [#698]相应删除了HeadersAlreadyExtractedrejectionExtensions不再可提取PR [#699]删除了ExtensionsAlreadyExtractedRequest as FromRequest::Rejection变为BodyAlreadyExtracted0.3.0FromRequest重构后BodyAlreadyExtracted被移除PR [#1272]0.3.1内置 rejection 增加body_text与status方法PR [#1612]0.5.0所有define_rejection!()生成的 rejection其Display输出现在包含内部错误的Display内容与body_text()输出对齐PR [#3118]0.4.5修复内部__log_rejection宏在 axum 系列 crate 某些 feature 组合下的编译错误PR [#2933]0.2.5自动处理http_body::LengthLimitError在FailedToBufferBody中将其映射为413 Payload Too LargePR [#1048]——这与DefaultBodyLimit的 2MB 上限配合构成请求体过大的完整错误链路。八、其他值得注意的版本变更汇总为便于升级与排查将 CHANGELOG 中其余重要变更归纳如下8.1 MSRV最低 Rust 版本演进版本MSRV对应变更0.2.61.56明确 axum-core 的 MSRVPR [#1098]0.5.0alpha.11.75为 RPITIT 铺路PR [#2943]0.5.31.78再次提升PR [#3412]Cargo.toml中通过rust-version { workspace true }与工作区统一管理 MSRV。0.5.x 系列要求 Rust 1.78这是使用return-position impl Trait in traits与#[diagnostic::on_unimplemented]等新特性的前提。8.2 打包与依赖清理0.5.4移除未使用的rustversion依赖PR [#3502]0.5.5无代码变更仅修复 docs.rs 构建0.5.1因意外破坏性变更见 PR [#3190]从 crates.io 撤回升级时请直接使用 0.5.2 及以上。8.3 类型与 trait 细节0.3.3为不使用就无意义的类型添加#[must_use]PR [#1809]0.1.2为bytes::BytesMut与bytes::ChainT, U实现IntoResponsePR [#767]0.5.2BodyDataStream实现Stream::size_hintPR [#3195]0.4.1修正from_stream文档中指向Stream的链接PR [#2391]0.4.0修复失效文档链接PR [#2164]明确将DefaultBodyLimit应用于单个路由的文档PR [#2157]。九、写在最后如何继续深入axum-core的完整源码位于 axum-core/src建议按以下顺序深入body.rs 与 body/unknown.rs理解Body的构造与未知大小语义extract/mod.rs 与 extract/default_body_limit.rs提取器体系与 body 限制机制response/into_response.rs 与 response/into_response_parts.rs元组响应组合逻辑与IntoResponseFailed/ForceStatusCode的状态码控制上游 axum 层axum 的路由与高层提取器axum/src/extract、axum/src/routing均建立在这些核心 trait 之上如 get_to_head.rs 演示了HEAD请求的自动处理与Body::unknown的场景相互印证。在升级到 axum 0.5.x 时重点检查三个兼容点OptionT提取器是否满足OptionalFromRequest(Parts)约束、是否已适配 RPITIT 带来的 trait 签名变化不再需要#[async_trait]、以及依赖你自定义提取器的第三方库是否同步升级。对于响应端若在 0.9 中遇到状态码没有被覆盖的意外请检查IntoResponseFailed扩展与ForceStatusCode的使用场景。【免费下载链接】axumHTTP routing and request-handling library for Rust that focuses on ergonomics and modularity项目地址: https://gitcode.com/GitHub_Trending/ax/axum创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表