Rust in Everything
基于 tower 0.5.3

在本站中

本站是开源的,仓库在 yuxuetr/rustineverything。这一部分的链接都指向同一个提交 89a61b1(2026-10-23),行号以它为准。站点 app 用的是 axum 0.8.9、tower 0.5.3、tower-http 0.6.11(以该提交的 Cargo.lock 为准)。app 的运行时代码不直接 use tower:tower 只出现在 [dev-dependencies] 里,给测试用。生产路径上的 tower 都是经由 axum 和 tower-http 间接用到的。

  1. 中间件栈:main.rs 里四次 Router::layer,后加的在外层。安全头挂在最外面,因为限流的 429 和尾斜杠跳转都是短路返回,只有包在它们外面的层才看得到这些响应。限流是手写的按 IP 令牌桶,不用 tower::limit::RateLimit:后者超限时让调用方等而不是拒绝,整个实例共用一个窗口,没有 Clone,而且 axum 每个请求都会复制一份服务。最后对比网关(Pingora)的钩子式写法。
  2. 不起服务器的测试:tower-http 的 ServeDir 本身是一个 Service,nest_service 直接挂上路由。Router 也是 Service,测试里用 ServiceExt::oneshot 发一个请求,不监听端口。还有一处要留意:没 with_state 的 Router 每个请求都会把 handler 外面的 layer 重新套一遍,带状态的 layer 在 oneshot 测试里和线上表现不一样。
flowchart TB
  req[HTTP 请求] --> sec[security_headers_mw]
  sec --> comp[CompressionLayer]
  comp --> slash[trailing_slash_mw]
  slash --> rl[rate_limit_mw]
  rl --> routes[路由]
  routes --> page[页面与 server fn]
  routes --> dir["ServeDir(nest_service)"]
  tst["测试:oneshot"] -.-> routes

💬 关联讨论

发起讨论
加载中...