From 27dc5e84275dd8233d074a44cd1534d019b8b797 Mon Sep 17 00:00:00 2001 From: Chris Glass Date: Thu, 25 Aug 2022 10:16:47 +0200 Subject: [PATCH 1/6] [doc] Added notes about extractor precedence Both JSON and Form extractors consume the Body when they run, so they need to be last in the order of extractors. Added a note in the structs docs themselves pointing to the relevant part of the documentation. --- axum/src/form.rs | 5 +++++ axum/src/json.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/axum/src/form.rs b/axum/src/form.rs index 414e1fd527..81b79baf8e 100644 --- a/axum/src/form.rs +++ b/axum/src/form.rs @@ -16,6 +16,11 @@ use std::ops::Deref; /// If used as an extractor `Form` will deserialize `application/x-www-form-urlencoded` request /// bodies into some target type via [`serde::Deserialize`]. /// +/// Since parsing form data requires consuming the request body, the `Form` extractor must be +/// *last* if there are multiple extractors in a handler. See ["the order of extractors"][order-of-extractors] +/// +/// [order-of-extractors]: extract/index.html#the-order-of-extractors +/// /// ```rust /// use axum::Form; /// use serde::Deserialize; diff --git a/axum/src/json.rs b/axum/src/json.rs index d49630fa54..04e9f47bf2 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -25,6 +25,11 @@ use std::ops::{Deref, DerefMut}; /// type. /// - Buffering the request body fails. /// +/// Since parsing JSON requires consuming the request body, the `Json` extractor must be +/// *last* if there are multiple extractors in a handler. See ["the order of extractors"][order-of-extractors] +/// +/// [order-of-extractors]: extract/index.html#the-order-of-extractors +/// /// See [`JsonRejection`] for more details. /// /// # Extractor example From 2895f46c73b7c64f1aeea85c8c6bc58e4380f44a Mon Sep 17 00:00:00 2001 From: Chris Glass Date: Thu, 25 Aug 2022 18:05:08 +0200 Subject: [PATCH 2/6] Address review comments - Added documentation snippet to BodyStream, RawBody, Multipart - Added documentation about the inner type of ContentLengthLimit - Fixed link type in State --- axum/src/extract/content_length_limit.rs | 8 ++++++++ axum/src/extract/multipart.rs | 6 ++++++ axum/src/extract/request_parts.rs | 11 +++++++++++ axum/src/extract/state.rs | 3 ++- axum/src/form.rs | 2 +- axum/src/json.rs | 5 +++-- 6 files changed, 31 insertions(+), 4 deletions(-) diff --git a/axum/src/extract/content_length_limit.rs b/axum/src/extract/content_length_limit.rs index a3d1f711c9..2590e0bdd8 100644 --- a/axum/src/extract/content_length_limit.rs +++ b/axum/src/extract/content_length_limit.rs @@ -6,9 +6,17 @@ use std::ops::Deref; /// Extractor that will reject requests with a body larger than some size. /// +/// /// `GET`, `HEAD`, and `OPTIONS` requests are rejected if they have a `Content-Length` header, /// otherwise they're accepted without the body being checked. /// +/// Note: `ContentLengthLimit` can wrap types that extract the body (for example, Form or Json) +/// if that is the case, the inner type will consume the request's body, which means the +/// ContentLengthLimit must come *last* if the handler uses several extractors. See +/// ["the order of extractors"][order-of-extractors] +/// +/// [order-of-extractors]: crate::extract#the-order-of-extractors +/// /// # Example /// /// ```rust,no_run diff --git a/axum/src/extract/multipart.rs b/axum/src/extract/multipart.rs index af0fe20236..98a1bf5f78 100644 --- a/axum/src/extract/multipart.rs +++ b/axum/src/extract/multipart.rs @@ -17,6 +17,12 @@ use std::{ /// Extractor that parses `multipart/form-data` requests (commonly used with file uploads). /// +/// Since extracting multipart form data from the request requires consuming it, the +/// `Multipart` extractor must be *last* if there are multiple extractors in a handler. +/// See ["the order of extractors"][order-of-extractors] +/// +/// [order-of-extractors]: crate::extract#the-order-of-extractors +/// /// # Example /// /// ```rust,no_run diff --git a/axum/src/extract/request_parts.rs b/axum/src/extract/request_parts.rs index eff77a2b34..933e7a71b2 100644 --- a/axum/src/extract/request_parts.rs +++ b/axum/src/extract/request_parts.rs @@ -103,6 +103,12 @@ where /// Extractor that extracts the request body as a [`Stream`]. /// +/// Since extracting the request body requires consuming it, the `BodyStream` extractor must be +/// *last* if there are multiple extractors in a handler. +/// See ["the order of extractors"][order-of-extractors] +/// +/// [order-of-extractors]: crate::extract#the-order-of-extractors +/// /// # Example /// /// ```rust,no_run @@ -173,6 +179,11 @@ fn body_stream_traits() { /// Extractor that extracts the raw request body. /// +/// Since extracting the raw request body requires consuming it, the `RawBody` extractor must be +/// *last* if there are multiple extractors in a handler. See ["the order of extractors"][order-of-extractors] +/// +/// [order-of-extractors]: crate::extract#the-order-of-extractors +/// /// # Example /// /// ```rust,no_run diff --git a/axum/src/extract/state.rs b/axum/src/extract/state.rs index 784709550c..aabeb000f9 100644 --- a/axum/src/extract/state.rs +++ b/axum/src/extract/state.rs @@ -11,7 +11,7 @@ use std::{ /// Note this extractor is not available to middleware. See ["Accessing state in /// middleware"][state-from-middleware] for how to access state in middleware. /// -/// [state-from-middleware]: ../middleware/index.html#accessing-state-in-middleware +/// [state-from-middleware]: crate::middleware#accessing-state-in-middleware /// /// # With `Router` /// @@ -22,6 +22,7 @@ use std::{ /// // /// // here you can put configuration, database connection pools, or whatever /// // state you need +/// // Note: the application state *must* derive `Clone` (or be wrapped in e.g. `Arc`) /// #[derive(Clone)] /// struct AppState {} /// diff --git a/axum/src/form.rs b/axum/src/form.rs index 81b79baf8e..43bddfc299 100644 --- a/axum/src/form.rs +++ b/axum/src/form.rs @@ -19,7 +19,7 @@ use std::ops::Deref; /// Since parsing form data requires consuming the request body, the `Form` extractor must be /// *last* if there are multiple extractors in a handler. See ["the order of extractors"][order-of-extractors] /// -/// [order-of-extractors]: extract/index.html#the-order-of-extractors +/// [order-of-extractors]: crate::extract#the-order-of-extractors /// /// ```rust /// use axum::Form; diff --git a/axum/src/json.rs b/axum/src/json.rs index 04e9f47bf2..472668727b 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -26,9 +26,10 @@ use std::ops::{Deref, DerefMut}; /// - Buffering the request body fails. /// /// Since parsing JSON requires consuming the request body, the `Json` extractor must be -/// *last* if there are multiple extractors in a handler. See ["the order of extractors"][order-of-extractors] +/// *last* if there are multiple extractors in a handler. +/// See ["the order of extractors"][order-of-extractors] /// -/// [order-of-extractors]: extract/index.html#the-order-of-extractors +/// [order-of-extractors]: crate::extract#the-order-of-extractors /// /// See [`JsonRejection`] for more details. /// From 1e60bfc7806415f10207970d197493a0dbe0b907 Mon Sep 17 00:00:00 2001 From: Chris Glass Date: Thu, 25 Aug 2022 18:22:48 +0200 Subject: [PATCH 3/6] Update axum/src/extract/content_length_limit.rs Co-authored-by: David Pedersen --- axum/src/extract/content_length_limit.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/axum/src/extract/content_length_limit.rs b/axum/src/extract/content_length_limit.rs index 2590e0bdd8..66909f078f 100644 --- a/axum/src/extract/content_length_limit.rs +++ b/axum/src/extract/content_length_limit.rs @@ -6,7 +6,6 @@ use std::ops::Deref; /// Extractor that will reject requests with a body larger than some size. /// -/// /// `GET`, `HEAD`, and `OPTIONS` requests are rejected if they have a `Content-Length` header, /// otherwise they're accepted without the body being checked. /// From 80479faca5883a34ee2d73772628e31e9ca3b159 Mon Sep 17 00:00:00 2001 From: Chris Glass Date: Thu, 25 Aug 2022 20:08:31 +0200 Subject: [PATCH 4/6] Cargo fmt didn't run for some reason I need to check my editor config... --- axum/src/extract/multipart.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/axum/src/extract/multipart.rs b/axum/src/extract/multipart.rs index 98a1bf5f78..8d774acf5d 100644 --- a/axum/src/extract/multipart.rs +++ b/axum/src/extract/multipart.rs @@ -17,12 +17,12 @@ use std::{ /// Extractor that parses `multipart/form-data` requests (commonly used with file uploads). /// -/// Since extracting multipart form data from the request requires consuming it, the -/// `Multipart` extractor must be *last* if there are multiple extractors in a handler. +/// Since extracting multipart form data from the request requires consuming it, the +/// `Multipart` extractor must be *last* if there are multiple extractors in a handler. /// See ["the order of extractors"][order-of-extractors] /// /// [order-of-extractors]: crate::extract#the-order-of-extractors -/// +/// /// # Example /// /// ```rust,no_run From 8cc144522c87e6920e563d293fa03f151ddfdf6e Mon Sep 17 00:00:00 2001 From: Chris Glass Date: Fri, 26 Aug 2022 09:41:54 +0200 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: David Pedersen --- axum/src/extract/content_length_limit.rs | 4 ++-- axum/src/extract/multipart.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/axum/src/extract/content_length_limit.rs b/axum/src/extract/content_length_limit.rs index 66909f078f..f1c58e1430 100644 --- a/axum/src/extract/content_length_limit.rs +++ b/axum/src/extract/content_length_limit.rs @@ -9,9 +9,9 @@ use std::ops::Deref; /// `GET`, `HEAD`, and `OPTIONS` requests are rejected if they have a `Content-Length` header, /// otherwise they're accepted without the body being checked. /// -/// Note: `ContentLengthLimit` can wrap types that extract the body (for example, Form or Json) +/// Note: `ContentLengthLimit` can wrap types that extract the body (for example, [`Form`] or [`Json`]) /// if that is the case, the inner type will consume the request's body, which means the -/// ContentLengthLimit must come *last* if the handler uses several extractors. See +/// `ContentLengthLimit` must come *last* if the handler uses several extractors. See /// ["the order of extractors"][order-of-extractors] /// /// [order-of-extractors]: crate::extract#the-order-of-extractors diff --git a/axum/src/extract/multipart.rs b/axum/src/extract/multipart.rs index 8d774acf5d..70b1620746 100644 --- a/axum/src/extract/multipart.rs +++ b/axum/src/extract/multipart.rs @@ -17,7 +17,7 @@ use std::{ /// Extractor that parses `multipart/form-data` requests (commonly used with file uploads). /// -/// Since extracting multipart form data from the request requires consuming it, the +/// Since extracting multipart form data from the request requires consuming the body, the /// `Multipart` extractor must be *last* if there are multiple extractors in a handler. /// See ["the order of extractors"][order-of-extractors] /// From 086fa09e81daa9d9b1454ce74161cf331182e353 Mon Sep 17 00:00:00 2001 From: Chris Glass Date: Fri, 26 Aug 2022 09:48:16 +0200 Subject: [PATCH 6/6] Add targets to links --- axum/src/extract/content_length_limit.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/axum/src/extract/content_length_limit.rs b/axum/src/extract/content_length_limit.rs index f1c58e1430..6e53af7b40 100644 --- a/axum/src/extract/content_length_limit.rs +++ b/axum/src/extract/content_length_limit.rs @@ -15,6 +15,8 @@ use std::ops::Deref; /// ["the order of extractors"][order-of-extractors] /// /// [order-of-extractors]: crate::extract#the-order-of-extractors +/// [`Form`]: crate::form::Form +/// [`Json`]: crate::json::Json /// /// # Example ///