Rust in Everything
基于 tower-http 0.7.1

tower-http

axum 的中间件就是 tower 的 Layer,所以它没有自己的一套静态文件、压缩或 CORS 实现,中间件文档开头就说「the ecosystem of tower and tower-http middleware all work with axum」。tower-http 不依赖 axum,操作的是 http::Request / http::Response 和 http_body::Body,同一个 CompressionLayer 也能套在纯 hyper 或其他基于 tower 的服务上。这一部分对着 tower-http 0.7.1 的源码,只讲 Web 应用最常用的几样,重点是每一样在请求的哪个点上起作用、自己会返回什么、和 axum 自己的机制怎么叠在一起。

  1. ServeDir 与 ServeFile:URI 先百分号解码再按段检查,.. 一律 404;目录无尾斜杠时 307 重定向(0.7.1 可关,挂在前缀下要配 redirect_path_prefix);按 Accept-Encoding 挑预压缩文件;单段 Range 与 ETag 条件请求;0.7.1 起 try_call 把 IO 错误交给调用方。
  2. 压缩:按 q 值和 zstd > br > gzip > deflate 的优先级选编码,拒绝一切时回 406;已编码、有 Content-Range、小于 32 字节、图片、gRPC、SSE 不压;压缩时去掉 Content-Length 和 Accept-Ranges、加 Vary;流式 body 边读边压。
  3. 其余常用中间件:TimeoutLayer 超时回一个空响应,包括读请求 body;RequestBodyLimitLayer 与 axum 的 DefaultBodyLimit 谁先触发;CorsLayer 拦下所有 OPTIONS;TraceLayer 的回调与分类器;CatchPanicLayer 只管到响应头为止。
flowchart TB
  client["客户端"] --> outer["Router::layer 的中间件"]
  outer --> cors["CorsLayer"]
  outer --> lim["RequestBodyLimitLayer"]
  outer --> tmo["TimeoutLayer"]
  outer --> cmp["CompressionLayer"]
  outer --> trace["TraceLayer、CatchPanicLayer"]
  outer --> router["路由"]
  router --> handler["handler"]
  router --> sd["nest_service:ServeDir"]

本卷锁定的是 tower-http 0.7.1;本站自己的代码目前锁在 0.6.11,两者对本站有影响的差异放在「在本站中」一章。

这一部分只讲「怎么用、在 axum 里会怎样」。tower-http 内部怎么组织、模块之间怎么复用、客户端方向的用法,以及这里没讲到的模块,见 tower-http 源码解析。

💬 关联讨论

发起讨论
加载中...