Rocket 里的 fairing,可以理解成:
控制塔的全局挂钩设施。
比如:
- 日志记录
- 统一响应头
- 启动时初始化
- 请求计时
- 响应加工
- 全局指标采集
官方也很明确提醒了一件事:
fairing 是 Rocket 提供的更简单的结构化中间件方式,但并不适合所有细粒度控制。很多情况下,request guard 或 data guard 会更干净。
这句话特别重要。
因为很多人会把 fairing 理解成“Rocket 版万能 middleware”。
不完全对。
更准确地说:
- guard 更像发射前检查员
- fairing 更像整座控制塔统一安装的设施
一个请求计时 fairing 例子大致像这样:
use rocket::{Data, Request, Response};
use rocket::fairing::{Fairing, Info, Kind};
pub struct RequestTimer;
#[rocket::async_trait]
impl Fairing for RequestTimer {
fn info(&self) -> Info {
Info {
name: "Request Timer",
kind: Kind::Request | Kind::Response,
}
}
async fn on_request(&self, req: &mut Request<'_>, _data: &mut Data<'_>) {
req.local_cache(|| std::time::SystemTime::now());
}
async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {
let start = req.local_cache(|| std::time::SystemTime::now());
if let Ok(duration) = start.elapsed() {
res.set_raw_header("x-response-time-ms", duration.as_millis().to_string());
}
}
}然后在构建时 attach:
rocket::build().attach(RequestTimer)你可以把它理解成:
控制塔统一给所有发射任务挂上计时器。
不是某个单独发射员临时拿秒表。
#Rocket 对 fairing 的真实态度
这点一定要讲透:
Rocket 官方文档明确提过,很多看似想用 fairing 做的事情,实际上更适合用 request guard、data guard 这些更可组合的机制。
所以别把 fairing 当成“一切都往这里塞”的万能箱。