diff --git a/docs-site/content/docs/getting-started/axum-users.md b/docs-site/content/docs/getting-started/axum-users.md index 2d6cf3de2..a33d369e0 100644 --- a/docs-site/content/docs/getting-started/axum-users.md +++ b/docs-site/content/docs/getting-started/axum-users.md @@ -45,7 +45,6 @@ In Loco you: server: middlewares: limit_payload: - enable: true body_limit: 5mb # .. more middleware below .. ``` diff --git a/docs-site/content/docs/the-app/controller.md b/docs-site/content/docs/the-app/controller.md index c4f4b6233..ada9591d7 100644 --- a/docs-site/content/docs/the-app/controller.md +++ b/docs-site/content/docs/the-app/controller.md @@ -270,7 +270,7 @@ This is the stack in `development` mode: ```sh $ cargo loco middleware --config -limit_payload {"enable":true,"body_limit":2000000} +limit_payload {"body_limit":{"Limit":1000000}} cors {"enable":true,"allow_origins":["any"],"allow_headers":["*"],"allow_methods":["*"],"max_age":null,"vary":["origin","access-control-request-method","access-control-request-headers"]} catch_panic {"enable":true} etag {"enable":true} @@ -294,8 +294,6 @@ Take what ever is enabled, and use `enable: false` with the relevant field. If ` ```yaml server: middlewares: - limit_payload: - enable: false cors: enable: false catch_panic: @@ -317,7 +315,6 @@ $ cargo loco middleware --config powered_by {"ident":"loco.rs"} -limit_payload (disabled) cors (disabled) catch_panic (disabled) etag (disabled) @@ -354,7 +351,7 @@ The result: ```sh $ cargo loco middleware --config -limit_payload {"enable":true,"body_limit":2000000} +limit_payload {"body_limit":{"Limit":1000000}} cors {"enable":true,"allow_origins":["any"],"allow_headers":["*"],"allow_methods":["*"],"max_age":null,"vary":["origin","access-control-request-method","access-control-request-headers"]} catch_panic {"enable":true} etag {"enable":true} @@ -372,7 +369,6 @@ Let's change the request body limit to `5mb`. When overriding a middleware confi ```yaml middlewares: limit_payload: - enable: true body_limit: 5mb ``` @@ -381,7 +377,7 @@ The result: ```sh $ cargo loco middleware --config -limit_payload {"enable":true,"body_limit":5000000} +limit_payload {"body_limit":{"Limit":5000000}} cors {"enable":true,"allow_origins":["any"],"allow_headers":["*"],"allow_methods":["*"],"max_age":null,"vary":["origin","access-control-request-method","access-control-request-headers"]} catch_panic {"enable":true} etag {"enable":true} @@ -480,19 +476,28 @@ To disable the middleware edit the configuration as follows: ## Limit Payload -Restricts the maximum allowed size for HTTP request payloads. -The middleware by default is enabled and configured to 2MB. +The Limit Payload middleware restricts the maximum allowed size for HTTP request payloads. By default, it is enabled and configured with a 2MB limit. -You can disable or customize this behavior in your config file. You can set a few options: +You can customize or disable this behavior through your configuration file. +### Set a custom limit ```yaml #... middlewares: limit_payload: - enable: true body_limit: 5mb ``` +### Disable payload size limitation +To remove the restriction entirely, set `body_limit` to `disable`: +```yaml +#... + middlewares: + limit_payload: + body_limit: disable +``` + + ##### Usage In your controller parameters, use `axum::body::Bytes`. ```rust diff --git a/src/controller/middleware/limit_payload.rs b/src/controller/middleware/limit_payload.rs index 313a93183..ebb5168a5 100644 --- a/src/controller/middleware/limit_payload.rs +++ b/src/controller/middleware/limit_payload.rs @@ -16,39 +16,50 @@ use serde::{Deserialize, Deserializer, Serialize}; use crate::{app::AppContext, controller::middleware::MiddlewareLayer, Result}; +#[derive(Debug, Clone, Copy, Deserialize, Serialize)] +pub enum DefaultBodyLimitKind { + Disable, + Limit(usize), +} + #[derive(Debug, Clone, Deserialize, Serialize)] pub struct LimitPayload { - #[serde(default)] - pub enable: bool, - #[serde(deserialize_with = "deserialize_body_limit")] - #[serde(default = "default_body_limit")] - pub body_limit: usize, + #[serde( + default = "default_body_limit", + deserialize_with = "deserialize_body_limit" + )] + pub body_limit: DefaultBodyLimitKind, } impl Default for LimitPayload { fn default() -> Self { Self { - enable: false, body_limit: default_body_limit(), } } } -fn default_body_limit() -> usize { - 2_000_000 +/// Returns the default body limit in bytes (2MB). +fn default_body_limit() -> DefaultBodyLimitKind { + DefaultBodyLimitKind::Limit(2_000_000) } -fn deserialize_body_limit<'de, D>(deserializer: D) -> Result +fn deserialize_body_limit<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { - Ok( - byte_unit::Byte::from_str(String::deserialize(deserializer)?) - .map_err(|err| serde::de::Error::custom(err.to_string()))? - .get_bytes() as usize, - ) -} + let s: String = String::deserialize(deserializer)?; + match s.as_str() { + "disable" => Ok(DefaultBodyLimitKind::Disable), + limit => { + let bytes = byte_unit::Byte::from_str(limit) + .map_err(|err| serde::de::Error::custom(err.to_string()))? + .get_bytes(); + Ok(DefaultBodyLimitKind::Limit(bytes as usize)) + } + } +} impl MiddlewareLayer for LimitPayload { /// Returns the name of the middleware fn name(&self) -> &'static str { @@ -57,7 +68,7 @@ impl MiddlewareLayer for LimitPayload { /// Returns whether the middleware is enabled or not fn is_enabled(&self) -> bool { - self.enable + true } fn config(&self) -> serde_json::Result { @@ -67,6 +78,11 @@ impl MiddlewareLayer for LimitPayload { /// Applies the payload limit middleware to the application router by adding /// a `DefaultBodyLimit` layer. fn apply(&self, app: AXRouter) -> Result> { - Ok(app.layer(axum::extract::DefaultBodyLimit::max(self.body_limit))) + let body_limit_layer = match self.body_limit { + DefaultBodyLimitKind::Disable => axum::extract::DefaultBodyLimit::disable(), + DefaultBodyLimitKind::Limit(limit) => axum::extract::DefaultBodyLimit::max(limit), + }; + + Ok(app.layer(body_limit_layer)) } } diff --git a/src/controller/middleware/mod.rs b/src/controller/middleware/mod.rs index b4a8ff30c..2f55ab455 100644 --- a/src/controller/middleware/mod.rs +++ b/src/controller/middleware/mod.rs @@ -24,7 +24,6 @@ pub mod static_assets; pub mod timeout; use axum::Router as AXRouter; -use limit_payload::LimitPayload; use serde::{Deserialize, Serialize}; use crate::{app::AppContext, environment::Environment, Result}; @@ -76,15 +75,7 @@ pub fn default_middleware_stack(ctx: &AppContext) -> Vec { + assert_eq!(res.status(), StatusCode::OK); + } + middleware::limit_payload::DefaultBodyLimitKind::Limit(_) => { + assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); + } } handle.abort();