Allan K
Allan K

Reputation: 497

Rust actix-web capturing HTTP error 413 (HTTP/1.1 413 Payload Too Large)

I am using actix-web. I would like to restrict the size of post request and have the web application capture this error log it and send back an informative error message to the user.

My code is given below. It seems the middleware gets run whether or not the limit is exceeded and HTTP code 413 raised. The accept_post is executed only when the limit has not been exceeded.

Is there a way of capturing this error in the middleware?

                .service(
                    web::scope("/hello_someone4")
                        .service(
                            web::resource("/there/*")
                                .app_data(web::PayloadConfig::default().limit(16))
                                .wrap(simple_middleware::simple_middleware_say_hi::SayHi)
                                .route(web::post().to(request_handlers2::accept_post))
                        )
                )

Upvotes: 2

Views: 1121

Answers (1)

Allan K
Allan K

Reputation: 497

The actix_web::middleware::errhandlers middleware provides the solutions I was seeking.

The example code below as obtained from "https://actix.rs/docs/middleware/". I can now add code to the render_413 function (shown below) to perform the logging.

use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
use actix_web::{dev, http, HttpResponse, Result};

fn render_500<B>(mut res: actix_web::dev::ServiceResponse<B>) -> actix_web::Result<actix_web::middleware::errhandlers::ErrorHandlerResponse<B>> {
    res.response_mut()
       .headers_mut()
       .insert(actix_web::http::header::CONTENT_TYPE, actix_web::http::HeaderValue::from_static("Error"));
    Ok(actix_web::middleware::errhandlers::ErrorHandlerResponse::Response(res))
}

fn render_413<B>(mut res: actix_web::dev::ServiceResponse<B>) -> actix_web::Result<actix_web::middleware::errhandlers::ErrorHandlerResponse<B>> {
    res.response_mut()
       .headers_mut()
       .insert(actix_web::http::header::CONTENT_TYPE, actix_web::http::HeaderValue::from_static("413 Error"));
    let req = res.request();
    let res = res.map_body(|_, _| actix_web::body::ResponseBody::Body(actix_web::dev::Body::from("{\"code\":413,\"error\":\"413 Payload Too Large\",\"message\":\"You've sent more data than expected\"}")).into_body());//alter the the response body see "https://users.rust-lang.org/t/actix-web-using-a-custom-error-handler-to-alter-the-response-body/41068"
    Ok(actix_web::middleware::errhandlers::ErrorHandlerResponse::Response(res))
}


#[actix_web::main]
async fn main() -> std::io::Result<()> {
    use actix_web::{web, App, HttpServer};

    HttpServer::new(|| {
        App::new()
                .wrap(
                    actix_web::middleware::errhandlers::ErrorHandlers::new()
                        .handler(actix_web::http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
                )
                .wrap(
                    actix_web::middleware::errhandlers::ErrorHandlers::new()
                        .handler(actix_web::http::StatusCode::PAYLOAD_TOO_LARGE, render_413),
                )
            )
            .service(
                web::resource("/test")
                    .route(web::get().to(|| HttpResponse::Ok()))
                    .route(web::head().to(|| HttpResponse::MethodNotAllowed())),
            )
            .service(
                web::scope("/hello_someone4")
                    .service(
                        web::resource("/there/*")
                            .app_data(web::PayloadConfig::default().limit(16))
                            .wrap(simple_middleware::simple_middleware_say_hi::SayHi)
                            .route(web::post().to(request_handlers2::accept_post))
                    )
            )
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

Upvotes: 2

Related Questions