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

Rust actix-web如何在中间件捕获413 Payload Too Large错误

解决方案

方案1:直接为PayloadConfig配置自定义错误处理器(最简便)

这个是专门处理Payload超限场景的最优解,你可以直接在设置大小限制的时候绑定错误处理逻辑,同时完成日志记录和自定义返回值,修改你的配置代码如下:

.service(
    web::scope("/hello_someone4")
        .service(
            web::resource("/there/*")
                .app_data(
                    web::PayloadConfig::default()
                        .limit(16)
                        // 自定义超限错误处理逻辑
                        .error_handler(|err, _req| {
                            // 记录错误日志
                            eprintln!("请求大小超出限制: {}", err);
                            // 构造自定义返回响应
                            actix_web::error::InternalError::from_response(
                                err,
                                actix_web::HttpResponse::PayloadTooLarge()
                                    .content_type("text/plain; charset=utf-8")
                                    .body("请求内容过大,当前接口最大允许16字节的请求体")
                            ).into()
                        })
                )
                .wrap(simple_middleware::simple_middleware_say_hi::SayHi)
                .route(web::post().to(request_handlers2::accept_post))
        )
)

方案2:在中间件中捕获413响应

如果你需要在中间件统一处理所有错误(包括413),可以修改你的中间件逻辑,在请求处理完成后读取响应状态码做判断,actix-web 4版本的中间件示例逻辑如下:

use actix_web::{
    dev::{Service, ServiceRequest, ServiceResponse},
    http::StatusCode,
    Error,
};
use futures::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

// 你的中间件服务实现
impl<S, B> Service<ServiceRequest> for SayHiMiddleware<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, req: ServiceRequest) -> Self::Future {
        let fut = self.service.call(req);
        Box::pin(async move {
            let res = fut.await?;
            // 在这里捕获413状态码的响应
            if res.status() == StatusCode::PAYLOAD_TOO_LARGE {
                // 记录日志
                eprintln!("捕获到请求大小超限错误,请求路径: {}", res.request().path());
                // 也可以在这里修改响应内容,返回自定义提示
            }
            Ok(res)
        })
    }
}

原理解释

Payload大小校验是actix-web在请求体提取阶段执行的,执行时机早于handler调用,所以超限情况下不会进入handler。但中间件包裹了完整的请求-响应流程,请求进入时会先执行中间件的前置逻辑,响应返回时也会经过中间件的后置逻辑,所以完全可以在中间件的响应处理阶段捕获到413错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 10:12:03