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

Actix Web中间件编译报错:类型不匹配与值已移动问题

Actix Web中间件编译错误解决方法

错误原因与解决方案

1. E0308 类型不匹配(预期()却找到Result<ServiceResponse<B>, _>)

问题出在call方法的返回值类型不符合要求:

  • call方法必须返回Pin<Box<dyn Future<Output = Result<ServiceResponse<B>, Error>>>>类型,而非直接返回Result。
  • 之前的代码可能在条件分支里直接返回了错误响应的Result,没有包裹成Future,也未用return终止分支,导致代码路径类型冲突。

2. E0382 值已移动(req在移动后被使用)

ServiceRequest是所有权类型:

  • 调用req.into_response(resp)会消耗req的所有权,如果之后代码还尝试使用req(比如修改头、传递给下一个服务),就会触发该错误。
  • 修正思路是先通过引用完成条件检查,仅在确定返回错误时才消耗req,其余场景使用可变引用修改请求头后正常传递。

修正后的完整代码

中间件实现

use actix_web::{dev::{Service, ServiceRequest, ServiceResponse, Transform}, Error, HttpResponse};
use futures::future::ok;
use std::{
    future::{Future, Ready},
    pin::Pin,
    task::{Context, Poll},
};

// 中间件结构体
pub struct HeaderMiddleware;

impl<S, B> Transform<S, ServiceRequest> for HeaderMiddleware
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type InitError = ();
    type Transform = HeaderMiddlewareService<S>;
    type Future = Ready<Result<Self::Transform, Self::InitError>>;

    fn new_transform(&self, service: S) -> Self::Future {
        ok(HeaderMiddlewareService { service })
    }
}

pub struct HeaderMiddlewareService<S> {
    service: S,
}

impl<S, B> Service<ServiceRequest> for HeaderMiddlewareService<S>
where
    S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
    S::Future: 'static,
    B: 'static,
{
    type Response = ServiceResponse<B>;
    type Error = Error;
    type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;

    fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.service.poll_ready(cx)
    }

    fn call(&self, mut req: ServiceRequest) -> Self::Future {
        // 1. 引用方式检查请求条件,不移动req所有权
        let is_valid = req.headers()
            .get("X-Valid-Header")
            .and_then(|h| h.to_str().ok())
            .map(|val| val == "allowed")
            .unwrap_or(false);

        if !is_valid {
            // 仅在返回错误时消耗req,包装成Future返回
            let err_resp = HttpResponse::Forbidden()
                .body("Request fails validation");
            return Box::pin(async { Ok(req.into_response(err_resp)) });
        }

        // 2. 用可变引用修改请求头,不转移所有权
        req.headers_mut().insert(
            "X-Middleware-Processed",
            actix_web::http::HeaderValue::from_static("true"),
        );

        // 3. 传递请求给下一个服务
        let next_fut = self.service.call(req);
        Box::pin(async move {
            let res = next_fut.await?;
            Ok(res)
        })
    }
}

主程序

use actix_web::{web, App, HttpServer, Responder};

async fn index() -> impl Responder {
    "Hello World!"
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .wrap(HeaderMiddleware)
            .route("/", web::get().to(index))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

内容的提问来源于stack exchange,提问作者user63898

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 08:03:28