mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-08 00:00:24 +02:00
Limit size of request bodies in Bytes extractor (#1346)
* Apply default limit to request body size * Support disabling the default limit * docs * changelog
This commit is contained in:
@@ -11,6 +11,7 @@ Types and traits for extracting data from requests.
|
||||
- [Accessing inner errors](#accessing-inner-errors)
|
||||
- [Defining custom extractors](#defining-custom-extractors)
|
||||
- [Accessing other extractors in `FromRequest` or `FromRequestParts` implementations](#accessing-other-extractors-in-fromrequest-or-fromrequestparts-implementations)
|
||||
- [Request body limits](#request-body-limits)
|
||||
- [Request body extractors](#request-body-extractors)
|
||||
- [Running extractors from middleware](#running-extractors-from-middleware)
|
||||
- [Wrapping extractors](#wrapping-extractors)
|
||||
@@ -620,6 +621,14 @@ let app = Router::new().route("/", get(handler)).layer(Extension(state));
|
||||
# };
|
||||
```
|
||||
|
||||
# Request body limits
|
||||
|
||||
For security reasons, [`Bytes`] will, by default, not accept bodies larger than
|
||||
2MB. This also applies to extractors that uses [`Bytes`] internally such as
|
||||
`String`, [`Json`], and [`Form`].
|
||||
|
||||
For more details, including how to disable this limit, see [`DefaultBodyLimit`].
|
||||
|
||||
# Request body extractors
|
||||
|
||||
Most of the time your request body type will be [`body::Body`] (a re-export
|
||||
@@ -816,6 +825,7 @@ async fn handler(
|
||||
```
|
||||
|
||||
[`body::Body`]: crate::body::Body
|
||||
[`Bytes`]: crate::body::Bytes
|
||||
[customize-extractor-error]: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs
|
||||
[`HeaderMap`]: https://docs.rs/http/latest/http/header/struct.HeaderMap.html
|
||||
[`Request`]: https://docs.rs/http/latest/http/struct.Request.html
|
||||
|
||||
@@ -16,7 +16,7 @@ mod request_parts;
|
||||
mod state;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use axum_core::extract::{FromRef, FromRequest, FromRequestParts};
|
||||
pub use axum_core::extract::{DefaultBodyLimit, FromRef, FromRequest, FromRequestParts};
|
||||
|
||||
#[doc(inline)]
|
||||
#[allow(deprecated)]
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use crate::{
|
||||
body::{Bytes, Empty},
|
||||
error_handling::HandleErrorLayer,
|
||||
extract::{self, FromRef, Path, State},
|
||||
extract::{self, DefaultBodyLimit, FromRef, Path, State},
|
||||
handler::{Handler, HandlerWithoutStateExt},
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, get_service, on, on_service, patch, patch_service, post, MethodFilter},
|
||||
test_helpers::*,
|
||||
BoxError, Json, Router,
|
||||
};
|
||||
use futures_util::stream::StreamExt;
|
||||
use http::{header::CONTENT_LENGTH, HeaderMap, Request, Response, StatusCode, Uri};
|
||||
use hyper::Body;
|
||||
use serde_json::json;
|
||||
@@ -604,6 +605,50 @@ async fn routes_must_start_with_slash() {
|
||||
TestClient::new(app);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn body_limited_by_default() {
|
||||
let app = Router::new()
|
||||
.route("/bytes", post(|_: Bytes| async {}))
|
||||
.route("/string", post(|_: String| async {}))
|
||||
.route("/json", post(|_: Json<serde_json::Value>| async {}));
|
||||
|
||||
let client = TestClient::new(app);
|
||||
|
||||
for uri in ["/bytes", "/string", "/json"] {
|
||||
println!("calling {}", uri);
|
||||
|
||||
let stream = futures_util::stream::repeat("a".repeat(1000)).map(Ok::<_, hyper::Error>);
|
||||
let body = Body::wrap_stream(stream);
|
||||
|
||||
let res_future = client
|
||||
.post(uri)
|
||||
.header("content-type", "application/json")
|
||||
.body(body)
|
||||
.send();
|
||||
let res = tokio::time::timeout(Duration::from_secs(3), res_future)
|
||||
.await
|
||||
.expect("never got response");
|
||||
|
||||
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn disabling_the_default_limit() {
|
||||
let app = Router::new()
|
||||
.route("/", post(|_: Bytes| async {}))
|
||||
.layer(DefaultBodyLimit::disable());
|
||||
|
||||
let client = TestClient::new(app);
|
||||
|
||||
// `DEFAULT_LIMIT` is 2mb so make a body larger than that
|
||||
let body = Body::from("a".repeat(3_000_000));
|
||||
|
||||
let res = client.post("/").body(body).send().await;
|
||||
|
||||
assert_eq!(res.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn limited_body_with_content_length() {
|
||||
const LIMIT: usize = 3;
|
||||
|
||||
Reference in New Issue
Block a user