如何在Actix Web中正确注册多个中间件?
Actix Web中正确注册多个Scope中间件的方法
你的代码里的中间件注册语法本身是合规的,web::scope("").wrap(Middleware1{}).wrap(Middleware2{})的写法应该能让两个中间件依次执行——请求进入时会先经过Middleware1,再到Middleware2,最后抵达业务handler;响应返回时则按相反顺序处理。
你遇到的Middleware1未执行问题,大概率出在中间件的实现逻辑上,常见原因包括:
Middleware1的call方法没有调用self.service.call(req),导致请求被中途拦截,无法传递到后续的Middleware2和handlerMiddleware1的Transformtrait实现存在缺陷,没有正确构建中间件调用链
以下是一个标准的中间件实现示例,你可以参考调整自己的Middleware1:
use actix_web::{dev::{Service, Transform}, Error, HttpRequest, HttpResponse}; use futures_util::future::{ok, Ready}; use std::task::{Context, Poll}; // Middleware1 结构体 pub struct Middleware1; // 实现 Transform trait,用于接入中间件链 impl<S, B> Transform<S, HttpRequest> for Middleware1 where S: Service<HttpRequest, Response = HttpResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Response = HttpResponse<B>; type Error = Error; type Transform = Middleware1Service<S>; type InitError = (); type Future = Ready<Result<Self::Transform, Self::InitError>>; fn new_transform(&self, service: S) -> Self::Future { ok(Middleware1Service { service }) } } // Middleware1 的服务实现 pub struct Middleware1Service<S> { service: S, } impl<S, B> Service<HttpRequest> for Middleware1Service<S> where S: Service<HttpRequest, Response = HttpResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Response = HttpResponse<B>; type Error = Error; type Future = S::Future; fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.poll_ready(cx) } fn call(&self, req: HttpRequest) -> Self::Future { // 这里添加你的 Middleware1 业务逻辑 println!("Middleware1 执行"); // 必须调用后续服务,否则请求会中断 self.service.call(req) } } // Middleware2 可参考同样的实现方式 pub struct Middleware2; impl<S, B> Transform<S, HttpRequest> for Middleware2 where S: Service<HttpRequest, Response = HttpResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Response = HttpResponse<B>; type Error = Error; type Transform = Middleware2Service<S>; type InitError = (); type Future = Ready<Result<Self::Transform, Self::InitError>>; fn new_transform(&self, service: S) -> Self::Future { ok(Middleware2Service { service }) } } pub struct Middleware2Service<S> { service: S, } impl<S, B> Service<HttpRequest> for Middleware2Service<S> where S: Service<HttpRequest, Response = HttpResponse<B>, Error = Error>, S::Future: 'static, B: 'static, { type Response = HttpResponse<B>; type Error = Error; type Future = S::Future; fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.poll_ready(cx) } fn call(&self, req: HttpRequest) -> Self::Future { println!("Middleware2 执行"); self.service.call(req) } }
只要中间件正确实现上述逻辑,你的注册代码就能正常触发两个中间件,请求阶段的执行顺序为Middleware1 → Middleware2 → handler。如果仍有问题,可以添加明确的日志输出,验证中间件的执行情况。
内容的提问来源于stack exchange,提问作者Finlay Weber
相关产品推荐
相关产品推荐

