From 0e6c3e168b1e9c287e630beb3bfa7366f95d44e7 Mon Sep 17 00:00:00 2001 From: David Pedersen Date: Mon, 7 Aug 2023 23:48:23 +0200 Subject: [PATCH] Clearly document applying `DefaultBodyLimit` to individual routes It was always possible to apply `DefaultBodyLimit` to invidual routes to have different limits for different routes. However we didn't make that clear in the docs. I've also added a test to make sure it actually works and doesn't regress in the future. --- axum-core/src/extract/default_body_limit.rs | 21 +++++++ axum/src/routing/tests/mod.rs | 69 +++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/axum-core/src/extract/default_body_limit.rs b/axum-core/src/extract/default_body_limit.rs index 5a2cd971b5..75f442c2bc 100644 --- a/axum-core/src/extract/default_body_limit.rs +++ b/axum-core/src/extract/default_body_limit.rs @@ -63,6 +63,27 @@ use tower_layer::Layer; /// extractors and want to sure a limit is also applied there then [`RequestBodyLimit`] should be /// used. /// +/// # Different limits for different routes +/// +/// `DefaultBodyLimit` can also be selectively applied to have different limits for different +/// routes: +/// +/// ``` +/// use axum::{ +/// Router, +/// routing::post, +/// body::Body, +/// extract::{Request, DefaultBodyLimit}, +/// }; +/// +/// let app = Router::new() +/// // this route has a different limit +/// .route("/", post(|request: Request| async {}).layer(DefaultBodyLimit::max(1024))) +/// // this route still has the default limit +/// .route("/foo", post(|request: Request| async {})); +/// # let _: Router = app; +/// ``` +/// /// [`Body::data`]: http_body::Body::data /// [`Bytes`]: bytes::Bytes /// [`Json`]: https://docs.rs/axum/0.6.0/axum/struct.Json.html diff --git a/axum/src/routing/tests/mod.rs b/axum/src/routing/tests/mod.rs index 2bfc84526b..59047644fa 100644 --- a/axum/src/routing/tests/mod.rs +++ b/axum/src/routing/tests/mod.rs @@ -738,6 +738,75 @@ async fn changing_the_default_limit() { assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); } +#[crate::test] +async fn changing_the_default_limit_differently_on_different_routes() { + let limit1 = 2; + let limit2 = 10; + + let app = Router::new() + .route( + "/limit1", + post(|_: Bytes| async {}).layer(DefaultBodyLimit::max(limit1)), + ) + .route( + "/limit2", + post(|_: Bytes| async {}).layer(DefaultBodyLimit::max(limit2)), + ) + .route("/default", post(|_: Bytes| async {})); + + let client = TestClient::new(app); + + let res = client + .post("/limit1") + .body(reqwest::Body::from("a".repeat(limit1))) + .send() + .await; + assert_eq!(res.status(), StatusCode::OK); + + let res = client + .post("/limit1") + .body(reqwest::Body::from("a".repeat(limit2))) + .send() + .await; + assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); + + let res = client + .post("/limit2") + .body(reqwest::Body::from("a".repeat(limit1))) + .send() + .await; + assert_eq!(res.status(), StatusCode::OK); + + let res = client + .post("/limit2") + .body(reqwest::Body::from("a".repeat(limit2))) + .send() + .await; + assert_eq!(res.status(), StatusCode::OK); + + let res = client + .post("/limit2") + .body(reqwest::Body::from("a".repeat(limit1 + limit2))) + .send() + .await; + assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); + + let res = client + .post("/default") + .body(reqwest::Body::from("a".repeat(limit1 + limit2))) + .send() + .await; + assert_eq!(res.status(), StatusCode::OK); + + let res = client + .post("/default") + // `DEFAULT_LIMIT` is 2mb so make a body larger than that + .body(reqwest::Body::from("a".repeat(3_000_000))) + .send() + .await; + assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); +} + #[crate::test] async fn limited_body_with_streaming_body() { const LIMIT: usize = 3;