如何在 wasm32 serverless 环境中使用 axum 路由处理单请求
【免费下载链接】axumHTTP routing and request-handling library for Rust that focuses on ergonomics and modularity项目地址: https://gitcode.com/GitHub_Trending/ax/axum
大多数 Rust 后端经验是“起一个 TCP 服务再处理请求”,但在 wasm serverless 运行时里这个前提不成立:没有长驻的监听器,运行时把单个请求交给你的导出函数,函数处理完返回单个响应。axum 的Handlertrait 与这个模型几乎一一对应,因此 axum 的路由、提取器(extractor)和 tower service 可以在wasm32-unknown-unknown环境中直接使用,只是不启动 HTTP 服务器。本文按 axum 仓库自带的 simple-router-wasm 示例 走一遍这条集成路径:配置依赖、写出单请求处理函数、运行并验证结果。
为什么 wasm 下必须关闭 axum 的默认特性
axum 的默认特性里包含tokio、http1等,它们会引入 tokio 及其 IO 层 mio。而 mio 不支持wasm32-unknown-unknown目标(示例代码头部注释的说明),所以在 wasm 环境下依赖 axum 时必须写default-features = false。仓库示例的 Cargo.toml 就是按这个方式声明的:
[dependencies] # `default-features = false` to not depend on tokio features which don't support wasm # you can still pull in tokio manually and only add features that tokio supports for wasm axum = { path = "../../axum", default-features = false } futures-executor = "0.3.21" http = "1.0.0" tower-service = "0.3.1"三个依赖各自的用途(均来自该文件):
axum = { ..., default-features = false }:核心要求。不依赖不支持 wasm 的 tokio 特性;如果需要,可以手动引入 tokio,但只开启 tokio 支持 wasm 的特性。futures-executor:提供block_on,用来在同步的main里驱动异步的 handler。http:提供Request类型,用于构造示例中的模拟请求。tower-service:提供Servicetrait,用来调用Router。
示例文件里还额外声明了axum-extra = { path = "../../axum-extra", default-features = false },注释说明它并没有被直接使用,只是顺带确认 axum-extra 也能在 wasm 下工作;如果你的任务只涉及路由,可以不加这一行。
注意上面的path = "../../axum"是因为该示例作为 axum 仓库 workspace 的成员,直接指向仓库内的 crate 源码。如果你在自己的独立项目里复用这段配置,把依赖改成你要发布的 axum crate 版本即可,default-features = false这一项必须保留;本仓库的示例本身不修改,直接按下一节引用即可。
编写单请求处理函数
serverless 运行时期望的接口是“接收一个请求、返回一个响应”。示例把app函数当作 handler,把main当作“原本的 serverless 运行时”——由main收到请求并调用app。完整代码(摘自 examples/simple-router-wasm/src/main.rs):
use axum::{ response::{Html, Response}, routing::get, Router, }; use futures_executor::block_on; use http::Request; use tower_service::Service; fn main() { let request: Request<String> = Request::get("https://serverless.example/api/") .body("Some Body Data".into()) .unwrap(); let response: Response = block_on(app(request)); assert_eq!(200, response.status()); } #[allow(clippy::let_and_return)] async fn app(request: Request<String>) -> Response { let mut router = Router::new().route("/api/", get(index)); let response = router.call(request).await.unwrap(); response } async fn index() -> Html<&'static str> { Html("<h1>Hello, World!</h1>") }对照这个结构,有几个要点决定代码能否成立:
- 函数签名就是接口本身。
app接收Request<String>(请求体类型是String,示例中最简单的选择),返回 axum 的Response。真实 serverless 环境中,这个函数对应运行时导出的入口,main只是用来本地模拟“收到请求”的环节。 - Router 作为 Service 被调用。
app内部用Router::new().route("/api/", get(index))构建路由,再走router.call(request).await。这里用的是tower-service的Servicetrait 调用方式,而不是axum::serve那种“绑定监听器、持续接请求”的服务方式——wasm 里没有 TCP,所以也不需要监听器。 - handler 写法与普通 axum 相同。
index就是一个标准 axum handler,返回Html<&'static str>。如示例注释所说,路由、extractor、tower service 等 axum 能力在 wasm 环境下都照常可用。 - 同步入口靠
block_on桥接。main是同步函数,用futures_executor::block_on(app(request))拿到Response,再对状态码做断言。
运行与验证
示例文件头部注释给出的运行方式是:
cargo run -p example-simple-router-wasm同时在示例注释中明确:这个示例应当始终可以通过--target wasm32-unknown-unknown编译。
验证方式就写在main函数里:
assert_eq!(200, response.status());- 请求命中
/api/路由 → handler 返回Html响应 → 状态码应为200; - 程序正常退出(断言不 panic)即说明路由在 wasm 配置下工作正常;
- 如果断言失败,说明路由没有命中预期 handler,需要检查
Router中注册的路径与请求 URI 是否一致。
适用边界
- 本模式只覆盖“单请求进、单响应出”的 serverless 函数形态。需要
axum::serve+ TCP 监听器的传统服务方式不属于本文路径:示例正是通过default-features = false排除掉不支持 wasm 的 tokio 特性。 - 示例代码中的
Request<String>、URI 和响应体都只是最简演示值;接真实 serverless 平台时,请求体类型和入口函数形态按平台要求调整,路由与 handler 部分的写法不变。
【免费下载链接】axumHTTP routing and request-handling library for Rust that focuses on ergonomics and modularity项目地址: https://gitcode.com/GitHub_Trending/ax/axum
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考