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
相关产品推荐
相关产品推荐

