You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Actix Web中正确注册多个中间件?

Actix Web中正确注册多个Scope中间件的方法

你的代码里的中间件注册语法本身是合规的,web::scope("").wrap(Middleware1{}).wrap(Middleware2{})的写法应该能让两个中间件依次执行——请求进入时会先经过Middleware1,再到Middleware2,最后抵达业务handler;响应返回时则按相反顺序处理。

你遇到的Middleware1未执行问题,大概率出在中间件的实现逻辑上,常见原因包括:

  • Middleware1的call方法没有调用self.service.call(req),导致请求被中途拦截,无法传递到后续的Middleware2和handler
  • Middleware1的Transform trait实现存在缺陷,没有正确构建中间件调用链

以下是一个标准的中间件实现示例,你可以参考调整自己的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 19:07:12