Actix Web,可以把它想成一座专门应对高并发车流的“分流要塞”。
这座要塞不是那种什么都包办的超级帝都,也不是一个只会裸接 TCP 的钢筋地基。它更像一套已经修好的高速城防系统:
- 城门很多,但进城规则极严
- 每条车道都有人值守,但值守方式极轻
- 每个请求一进门,就会被迅速分流、核验、取件、送往对应处理官
- 处理官在等外部资源时,不会傻站在门口堵路
- 真正需要共享的仓库会被严格上锁,不需要共享的就分给各个守备队自己保管
这就是 Actix Web 的气质:高性能、强类型、偏工程实战、不是玩具,也不是“全家桶神框架”。
#一、为什么会有这座要塞
Rust 世界需要 Actix Web,本质上是因为传统 Web 服务有一个长期矛盾:
- 你想要高吞吐、低延迟
- 你又不想在并发、内存、安全、类型上靠“自觉”
- 你还希望写出来不是纯底层管道,而是一个可维护的服务框架
如果只追求底层控制,你可以直接去用 hyper 这一类更底层的 HTTP 引擎;但那更像你自己在荒地上砌城墙。
Actix Web 的存在意义,就是把 Rust 的 async/await、Tokio 运行时、类型系统、服务抽象,组织成一座能直接投入生产的分流要塞。
它解决的不是“怎么发一个 Hello World 响应”,而是这些更现实的问题:
- 大量请求怎么稳稳接住
- 路由怎么组织
- 参数怎么安全提取
- 中间件怎么插
- 错误怎么统一出城
- 状态怎么共享而不把吞吐打烂
- 异步等待怎么不堵住工作线程
#二、Rust Web 里的 Actix Web,站在什么位置
如果把 Rust Web 世界看成一片交通基建带,大致可以这样理解:
hyper:发动机和底盘tower:标准化的管线接口axum:更偏 Tower 原教旨的高速公路系统actix-web:更像一座已经修好城门、检查口、分流道、登记厅的高性能要塞
Actix Web 到 2026-03-28 的稳定认知有两个重点:
- 它是 Rust Web 主流路线之一。
- 今天别再把它理解成“actor 框架外壳”。
早期很多人一提 Actix 就想到 actor,但 Actix Web 官方文档已经明确:Actix Web 现在与 actor 框架已经大体分离。你今天学 Actix Web,主线心智不是 actor,而是:
HttpServerAppworkerrouteextractormiddlewareResponseError- Tokio 上的异步执行
所以,现代 Actix Web 的正确打开方式不是“我先学 actor 模型”,而是“我先学这座要塞怎么分流”。
#三、最重要的心智模型:HttpServer、App、worker 到底谁是谁
这一段如果你吃透了,后面 70% 的 Actix Web 都会顺。
把它们想成下面这套结构:
外部请求车流
|
v
[ HttpServer 总分流塔 ]
|
| 监听端口 / 接收连接 / 分配到值守队
|
+-------------------+-------------------+-------------------+
| | |
v v v
[ worker 1 ] [ worker 2 ] [ worker N ]
单线程守备队 单线程守备队 单线程守备队
| | |
v v v
[ App 实例 ] [ App 实例 ] [ App 实例 ]
城内规则册 城内规则册 城内规则册
|
v
中间件走廊
|
v
路由分发台
|
v
extractor 登记官
|
v
handler 处理官
|
+------> 本地/共享状态仓库
+------> 数据库 / Redis / MQ / 外部 API
|
v
响应出城现在分别看:
#1. HttpServer:总分流塔
HttpServer 负责:
- 监听端口
- 接受连接
- 启动多个 worker
- 把流量分配给 worker
- 管理优雅停机、超时、TLS 等外围能力
它不是“业务本体”,它是要塞的总调度塔。
#2. worker:值守守备队
Actix Web 默认会启动多个 HTTP worker。官方文档给出的稳定心智是:
- 默认 worker 数接近机器可用并行度
- 每个 worker 是独立线程
- 每个 worker 都会拿到自己的一份 App 实例
- 每个 worker 内部跑的是单线程异步运行时
这句话非常关键。
很多人一看到“多 worker”就以为每个请求都在一个巨大的共享线程池里乱窜。不是。Actix Web 更像是:
- 城门外有总调度
- 城内有多支守备队
- 每支守备队各守自己那条线
- 同一支队内部处理大量异步任务,但这条线本身是单线程值守
这带来两个非常重要的结果:
- worker 内部不共享的状态,心智更简单
- 想跨 worker 共享状态时,你才需要显式引入同步代价
#3. App:每个 worker 手里那本城内规则册
App 不是整个服务器唯一的全局单例。
这是 Actix Web 初学者最容易踩的坑。
App 里通常放:
- 路由
- scope
- middleware
- app data
- 各种 service 配置
但要记住:HttpServer::new(|| App::new()...) 这个闭包,是“造规则册的工厂”。worker 起几个,App 就会被实例化几份;如果你绑定多个地址,实例化次数还会更多。
所以正确理解是:
HttpServer= 总分流塔App= 每个 worker 自己持有的一本规则册worker= 真正值守处理请求的守备队
#四、路由:这座要塞怎么决定“你该去哪个门”
Actix Web 的路由就是城内道路系统。
最常见的几种组织方式:
App::route():快速挂单条路线App::service():挂资源web::scope():给一大片区域加统一前缀- 宏路由:
#[get]、#[post]这类声明式门牌
一个很实用的心智是:
App:整座要塞scope("/api"):东城 API 区resource("/users/{id}"):某个具体城门route(web::get().to(handler)):这个城门上哪种请求由谁接待
例如:
use actix_web::{web, App, HttpServer, HttpResponse};
async fn health() -> HttpResponse {
HttpResponse::Ok().body("ok")
}
async fn get_user(path: web::Path<(u64,)>) -> HttpResponse {
let user_id = path.into_inner().0;
HttpResponse::Ok().body(format!("user {}", user_id))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(
web::scope("/api")
.route("/health", web::get().to(health))
.route("/users/{id}", web::get().to(get_user))
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}你要把路由匹配想成“要塞门牌匹配”:
- 先看前缀区块
- 再看资源路径
- 再看方法和 guard
- 第一个匹配到的就停下,不会继续往后找
所以路由顺序、资源顺序、guard 条件,都会影响最终命中。
#五、extractor:登记官为什么是 Actix Web 的灵魂
Actix Web 最有代表性的机制之一,就是 extractor。
请求到了城门口,处理官不应该自己在一大坨原始请求里手扒:
- 路径参数
- 查询参数
- JSON body
- 表单
- header
- 状态对象
而应该由登记官提前把材料分类装订好,再交给处理官。
这就是 extractor。
常见 extractor:
web::Path<T>:路径参数web::Query<T>:查询参数web::Json<T>:JSON 请求体web::Form<T>:表单web::Data<T>:应用状态HttpRequest:原始请求对象Bytes/String/Payload:更底层的 body 读取方式
看一个典型例子:
use actix_web::{web, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct UserPath {
id: u64,
}
#[derive(Deserialize)]
struct UserQuery {
verbose: Option<bool>,
}
#[derive(Serialize)]
struct UserView {
id: u64,
name: String,
verbose: bool,
}
async fn get_user(
path: web::Path<UserPath>,
query: web::Query<UserQuery>,
) -> impl Responder {
let path = path.into_inner();
let query = query.into_inner();
web::Json(UserView {
id: path.id,
name: "fortress-user".into(),
verbose: query.verbose.unwrap_or(false),
})
}这段代码的意思不是“框架在帮你偷懒”,而是:
- 路径参数先由登记官提取
- 查询参数先由登记官提取
- 处理官拿到的已经是类型安全的材料
这会带来三个巨大的工程收益:
- 参数解析逻辑不散落
- 类型错误尽早暴露
- handler 只写业务,不写拆包流水账
不过这里有一个非常重要的规则:
会消费 body 的 extractor,通常只有第一个能成功读取。
也就是说你不能理直气壮地同时写:
- 一个
web::Json<T> - 再来一个
Bytes
因为 body 流不是无限复制的。城门口的材料包被第一个登记官拆走了,后面的人就拿不到原件了。
#六、state:仓库该放哪里,决定这座要塞是快还是堵
Actix Web 的状态管理,核心不是“能不能共享”,而是“你到底该不该共享”。
先记最重要的一条:
如果你想在多个 worker 之间共享状态,web::Data 通常要在 HttpServer::new 外面构造。
因为 Data 内部是基于 Arc 的,克隆成本很低,适合把同一个共享仓库分发给各个守备队。
看一个完整点的例子:
use std::sync::atomic::{AtomicU64, Ordering};
use actix_web::{
http::StatusCode,
middleware::{Logger, NormalizePath},
web, App, HttpResponse, HttpServer, ResponseError,
};
use serde::{Deserialize, Serialize};
use thiserror::Error;
struct AppState {
app_name: String,
request_count: AtomicU64,
}
#[derive(Debug, Deserialize)]
struct UserPath {
id: u64,
}
#[derive(Debug, Deserialize)]
struct UserQuery {
page: Option<u32>,
}
#[derive(Debug, Deserialize)]
struct CreateUser {
name: String,
}
#[derive(Debug, Serialize)]
struct UserView {
id: u64,
name: String,
page: u32,
served_by: String,
}
#[derive(Debug, Error)]
enum ApiError {
#[error("user not found")]
NotFound,
#[error("invalid input: {0}")]
BadRequest(String),
}
impl ResponseError for ApiError {
fn status_code(&self) -> StatusCode {
match self {
Self::NotFound => StatusCode::NOT_FOUND,
Self::BadRequest(_) => StatusCode::BAD_REQUEST,
}
}
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code()).body(self.to_string())
}
}
async fn health(state: web::Data<AppState>) -> HttpResponse {
let total = state.request_count.load(Ordering::Relaxed);
HttpResponse::Ok().body(format!("{} alive, requests={}", state.app_name, total))
}
async fn get_user(
path: web::Path<UserPath>,
query: web::Query<UserQuery>,
state: web::Data<AppState>,
) -> Result<web::Json<UserView>, ApiError> {
state.request_count.fetch_add(1, Ordering::Relaxed);
if path.id == 404 {
return Err(ApiError::NotFound);
}
Ok(web::Json(UserView {
id: path.id,
name: "fortress-user".into(),
page: query.page.unwrap_or(1),
served_by: state.app_name.clone(),
}))
}
async fn create_user(
payload: web::Json<CreateUser>,
state: web::Data<AppState>,
) -> Result<HttpResponse, ApiError> {
state.request_count.fetch_add(1, Ordering::Relaxed);
if payload.name.trim().is_empty() {
return Err(ApiError::BadRequest("name cannot be empty".into()));
}
Ok(HttpResponse::Created().body(format!("created {}", payload.name)))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
let state = web::Data::new(AppState {
app_name: "fortress-api".into(),
request_count: AtomicU64::new(0),
});
HttpServer::new(move || {
App::new()
.app_data(state.clone())
.wrap(Logger::default())
.wrap(NormalizePath::trim())
.service(
web::scope("/api")
.route("/health", web::get().to(health))
.route("/users/{id}", web::get().to(get_user))
.route("/users", web::post().to(create_user))
)
})
.workers(std::thread::available_parallelism()?.get())
.bind(("127.0.0.1", 8080))?
.run()
.await
}这里你应该看到几个关键点:
state在HttpServer::new外面构造,表示它是真共享仓库- handler 里通过
web::Data<AppState>取状态 - 高频计数用
AtomicU64,避免无脑上大锁 - 错误通过
ResponseError统一出城
还要再补一条高级但非常实用的认知:
Actix Web 的路由层会“就近取 state”。
也就是:
App上挂了一份Data<T>- 某个
scope又挂了一份同类型Data<T>
那么进入这个 scope 的请求,会优先拿到“更近”的那一份。就像东城区先用东城仓库,不会回中央总仓。
#七、middleware:护城河、安检廊、审计官
如果说 extractor 是“登记官”,那 middleware 就是“沿路检查设施”。
它能做的事包括:
- 请求前置校验
- 日志
- 默认响应头
- 路径规范化
- 会话
- 错误响应加工
- 指标统计
- 提前拦截直接返回
Actix Web 的 middleware 一个必须记住的规则是:
注册顺序和执行顺序相反。后 wrap() 的,先执行。
这就像你穿过多道安检廊,最后装上的那道门,最先拦住来人。
官方已经把很多常用设施准备好了:
LoggerNormalizePathDefaultHeadersCompressErrorHandlers
而且现在写简单中间件时,不必一上来就硬啃 Transform/Service,可以直接用 from_fn。
例如一个最小自定义中间件:
use actix_web::{
body::MessageBody,
dev::{Service, ServiceRequest, ServiceResponse},
middleware::{from_fn, Next},
App, Error,
};
async fn timing_mw(
req: ServiceRequest,
next: Next<impl MessageBody>,
) -> Result<ServiceResponse<impl MessageBody>, Error> {
let started = std::time::Instant::now();
let res = next.call(req).await?;
println!("request took: {:?}", started.elapsed());
Ok(res)
}
// App::new().wrap(from_fn(timing_mw));把 middleware 想成要塞里的几层设施最容易理解:
Logger:审计官NormalizePath:纠偏路牌- 认证中间件:身份安检门
- 压缩中间件:出城打包站
ErrorHandlers:事故公关办
#八、错误处理:事故不是不能发生,而是不能乱响警报
Actix Web 的错误处理主心智,不是“到处 unwrap”,而是:
- handler 正常返回响应
- 出问题时返回
Result<T, E> E尽量实现ResponseError- 框架根据你的错误类型,自动决定 HTTP 状态码和响应内容
这就是为什么 ResponseError 很重要。它像要塞里的事故分级手册:
- 这是 400,说明来访材料不合规
- 这是 404,说明你找的门不存在
- 这是 401/403,说明权限不够
- 这是 500,说明城内设备故障,但不该把内部细节全喊给外面听
成熟项目里最好把错误分成两层:
- 对内错误:日志里保留完整上下文
- 对外错误:只暴露安全、可理解的信息
Actix Web 也会按官方规则记录错误日志。默认错误会进入日志;调高日志级别并开启回溯时,排障信息会更完整。
#九、异步与性能来源:这座要塞为什么快
很多人说 Actix Web 快,但“快”不能只背结论,要知道它快在哪。
把请求处理想成“值守官处理来车”:
- 如果值守官查库存要 20ms,他不该站在门口发呆 20ms
- 正确做法是把这个等待挂起,让这条线先处理别的车
- 等库存回来了,再接着办这单
这就是异步 I/O 的本质。
Actix Web 的性能来源,主要不是某个神秘魔法,而是几层结构一起生效:
#1. Rust 原生可执行产物
- 没有解释器层
- 没有运行时反射式 DI 的大额开销
- 没有 GC 停顿这一类常见尾延迟来源
#2. 跑在 Tokio 上
Actix Web 官方文档明确:Actix Web 运行在 Tokio 上。
这意味着:
- 你能接入大量 Tokio 生态
- 你可以使用成熟的 async 数据库/网络库
- 异步等待不会白白堵住 worker 线程
#3. worker 模型很清楚
每个 worker 单线程值守,减少了“同一路请求在多个线程之间乱跳”的协调复杂度。不是没有并发,而是把并发组织得很有秩序。
#4. 尽量少共享,必须共享时显式付费
每个 worker 拿自己那份 App,天然避免了一部分无意义共享。你真的要共享时,再通过 Data、原子类型、锁来付代价。
这比“默认万物全局共享”更容易保住吞吐。
#5. 类型驱动的参数提取与响应
请求怎么拆、响应怎么出,很多都在编译期被约束住了。运行时少猜、少反射、少动态兜底,路径就更短。
不过一定要记住:
Actix Web 快,不代表你写什么都快。
下面这些东西会把要塞自己堵死:
- 在 async handler 里直接跑阻塞 I/O
- 长时间持有
Mutex - 持锁跨
await - 用同步数据库驱动硬塞进 async 路线
- 把所有请求都去抢一个全局大锁
- 大量 CPU 密集任务直接塞在请求线程里
Actix Web 快的前提是:你配得上它的分流模型。
#十、一个完整请求,在要塞里到底怎么走
把一次请求流程串起来,你就会更稳:
客户端发起 GET /api/users/7?page=2
|
v
HttpServer 接到连接
|
v
分配给某个 worker
|
v
进入这个 worker 的 App 实例
|
v
经过 middleware
后 wrap 的先执行
|
v
路由匹配 /api/users/{id}
|
v
extractor 提取:
- Path<UserPath> => id = 7
- Query<UserQuery> => page = 2
- Data<AppState> => 共享仓库句柄
|
v
handler 执行业务
|
+--> 需要查 DB / Redis / 外部 API 时 await
|
v
返回 Json / HttpResponse / Result<T, E>
|
v
若 E 实现了 ResponseError,则自动转 HTTP 响应
|
v
响应再穿过 middleware 出城你会发现,Actix Web 其实没有那么玄学。它只是把每一层职责都切得很干净。
#十一、常见误区:很多人不是不会用,是把要塞想错了
#误区 1:把 App 当成全局唯一单例
错。App 是由 HttpServer::new 的工厂闭包按 worker 实例化出来的。
后果是:
- 你把计数器写在闭包里面,以为全局共享,结果其实每个 worker 一份
- 你把初始化写错位置,结果行为和预期完全不同
#误区 2:所有 state 都塞进 Mutex<HashMap<...>>
这是最经典的“把中央总仓修成唯一瓶颈”。
能不用共享可变状态,就别共享。
能用原子类型,就别大锁。
真要上锁,也尽量缩短锁持有时间,别拿着锁过 await。
#误区 3:在 async handler 里跑阻塞代码
例如:
- 同步文件 I/O
- 同步数据库客户端
std::thread::sleep- 大量 CPU 运算直接硬算
这会直接堵住 worker。值守官被一辆重卡卡在门口,后面的车全排长队。
#误区 4:以为 extractor 可以随便重复读取 body
不行。谁先拆包,谁先拿走材料。 如果你既想校验 body,又想保留原始字节,要专门设计这条链路。
#误区 5:middleware 顺序想反了
wrap(A).wrap(B).wrap(C),通常是 C 先入,A 后入。
别把安检门顺序装反。
#误区 6:用了 NormalizePath 却还乱定义尾斜杠路由
路径规范化和你的路由定义风格要统一。 否则会出现“看着像有门,实际上永远进不去”的怪现象。
#误区 7:还把 WebSocket 主线理解成旧 actor 路子
到 2026 的稳定主心智里,WebSocket 的现代高层路径是 actix-ws,不是继续把旧 actor 方式当默认主路。
#十二、Actix Web 适合什么,不适合什么
#适合的场景
- 高并发 JSON API
- 网关、BFF、聚合层
- webhook 接入站
- 内部基础服务
- I/O 密集型服务
- 对尾延迟和资源占用比较敏感的系统
- 团队本身就接受 Rust 的工程门槛
这类场景里,Actix Web 像一座特别合适的分流要塞:入口规矩多,但进来后秩序非常好。
#不太适合的场景
- 团队主要是 Python/TS,目标是最快业务试错
- 你想要像 NestJS 一样很重的模块化 DI 组织感
- 你想要像 FastAPI 那样极快起手并自动长出 OpenAPI 体验
- 你的业务是大量 CPU 密集计算,却又不准备做任务拆分或离线化
- 你主要跑的是边缘函数/非长期驻留服务器环境
Actix Web 不是不能做这些,而是它不是这些场景的默认最优武器。
#十三、和 Axum、NestJS、FastAPI、Express 怎么看
这一段不要用“谁吊打谁”的思路,要用“哪座城市适合哪种交通系统”的思路。
| 框架 | 最像什么 | 核心心智 | 默认优势 | 默认代价 |
|---|---|---|---|---|
| Actix Web | 高性能分流要塞 | HttpServer + worker + App + extractor |
吞吐强、控制力强、成熟实战感强 | Rust 学习曲线、工程门槛高 |
| Axum | 标准件高速公路系统 | Router + Tower Service + State |
Tokio/Tower 生态贴合度高、抽象统一 | 更偏原教旨,类型组合感更重 |
| NestJS | 政务大楼总包 | Module + Controller + Provider + DI |
企业组织性强、规范感强 | 运行时层更重 |
| FastAPI | 智能报关大厅 | 类型注解 + 依赖注入 + OpenAPI | 开发快、文档体验极好 | Python 在极高并发和 CPU 密集上先天不占优 |
| Express | 路边轻岗亭 | req / res / next |
轻、自由、上手快 | 大项目秩序靠团队自觉 |
再把重点掰开说:
#Actix Web vs Axum
这是 Rust 圈最常见的一组比较。
- Actix Web 更像“成型要塞”
- 有自己比较鲜明的 worker 心智
- extractor、middleware、路由组织都很完整
- 实战手感更像成熟框架
- Axum 更像“标准化高速公路”
- 跟 Tower、Hyper、Tokio 的抽象咬合更紧
- 很适合喜欢标准 service/layer 体系的人
- 对很多 Rust 基础抽象更友好,也更“硬核”
如果你喜欢“框架已经把城门修好”,Actix Web 很顺手。 如果你喜欢“整个系统都建立在统一标准件之上”,Axum 很顺手。
#Actix Web vs NestJS
- NestJS 赢在组织治理、模块化、依赖注入、企业团队协作体验
- Actix Web 赢在原生性能、资源效率、并发安全边界
NestJS 像一栋制度严明的大楼。 Actix Web 像一座吞吐极强的城防系统。
#Actix Web vs FastAPI
- FastAPI 的最大优势是开发速度、文档体验、依赖注入和 Python 生态
- Actix Web 的最大优势是吞吐、内存效率、并发控制和编译期约束
FastAPI 很适合快速建报关大厅。 Actix Web 更适合把报关大厅修成抗高峰冲击的钢筋堡垒。
#Actix Web vs Express
这俩其实不是一个重量级。
- Express 的魅力在于轻和自由
- Actix Web 的魅力在于稳和快
Express 像一个路边岗亭,搭起来快,扩起来全靠经验。 Actix Web 像一座专业交通枢纽,修起来讲究,但成了以后不容易塌。
#十四、收尾:真正学会 Actix Web,不是会写路由,而是脑子里有要塞图
如果你学到最后,只记住一句话,那就记住这句:
Actix Web 是一座把请求分流、材料提取、状态访问、异步等待、错误出城都组织得很严格的高性能要塞。
它为什么存在?
- 因为 Rust 需要一个既快又能直接干活的 Web 框架。
它在 Rust Web 里是什么位置?
- 是主流生产级路线之一,偏高性能、偏工程实战,不再以 actor 作为默认主线理解。
它最核心的心智模型是什么?
HttpServer是总分流塔worker是守备队App是每支守备队手里的规则册route是道路系统extractor是登记官state是仓库middleware是安检廊和审计官ResponseError是事故分级手册
你只要把这张要塞图装进脑子里,后面不管是接数据库、做鉴权、加日志、做网关、加 WebSocket、接 Redis,都会变成“在既有城防系统上继续修设施”,而不是“每次都重新理解一遍框架”。
这就是 Actix Web 最强的地方。
它不是让你觉得“好像很高级”。
它是让你在高流量真正来袭时,知道这座城为什么扛得住。
#官方来源链接清单
- Actix Web 官网:https://actix.rs/
- Actix Web 文档入口:https://actix.rs/docs/
- What is Actix Web:https://actix.rs/docs/whatis/
- Application(
App、scope、state):https://actix.rs/docs/application/ - Server(
HttpServer、worker、多线程):https://actix.rs/docs/server/ - URL Dispatch(路由、匹配、scope、guard):https://actix.rs/docs/url-dispatch/
- Extractors(
FromRequest、Path、Query、Json等):https://actix.rs/docs/extractors/ - Handlers(
Responder、返回类型):https://actix.rs/docs/handlers/ - Errors(
ResponseError、错误辅助函数、日志):https://actix.rs/docs/errors/ - Middleware(内置中间件、执行顺序):https://actix.rs/docs/middleware/
actix-webAPI 文档(docs.rs):https://docs.rs/actix-web/latest/actix_web/HttpServerAPI:https://docs.rs/actix-web/latest/actix_web/struct.HttpServer.htmlAppAPI:https://docs.rs/actix-web/latest/actix_web/struct.App.htmlweb::DataAPI:https://docs.rs/actix-web/latest/actix_web/web/struct.Data.htmlactix_web::rt(Tokio 运行时集成):https://docs.rs/actix-web/latest/actix_web/rt/middleware::from_fn:https://docs.rs/actix-web/latest/actix_web/middleware/fn.from_fn.htmlactix-session(现代 session 中间件):https://docs.rs/actix-session/latest/actix_session/- Actix WebSockets 指南:https://actix.rs/docs/websockets/
actix-ws(现代 WebSocket 路线):https://docs.rs/actix-ws/latest/actix_ws/- Axum 官方文档:https://docs.rs/axum/latest/axum/
- NestJS Controllers:https://docs.nestjs.com/controllers
- NestJS Middleware:https://docs.nestjs.com/middleware
- NestJS Providers:https://docs.nestjs.com/components
- FastAPI 官方站点:https://fastapi.tiangolo.com/
- FastAPI Dependencies:https://fastapi.tiangolo.com/tutorial/dependencies/
- FastAPI Middleware:https://fastapi.tiangolo.com/tutorial/middleware/
- Express Routing:https://expressjs.com/en/guide/routing.html
- Express Middleware:https://expressjs.com/en/guide/writing-middleware.html