diff --git a/Cargo.toml b/Cargo.toml index a221fbc5a9..41a3f49d67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,6 @@ members = [ # with `cargo +nightly update -Z minimal-versions` "internal-minimal-versions", ] + +[patch.crates-io] +hyper = { git = "https://github.com/hyperium/hyper", branch = "david/body-wrap-body" } diff --git a/axum-core/Cargo.toml b/axum-core/Cargo.toml index 4d6e74e71d..1b7f742cc2 100644 --- a/axum-core/Cargo.toml +++ b/axum-core/Cargo.toml @@ -16,10 +16,10 @@ bytes = "1.0" futures-util = { version = "0.3", default-features = false, features = ["alloc"] } http = "0.2.7" http-body = "0.4.5" +hyper = "0.14" mime = "0.3.16" [dev-dependencies] axum = { path = "../axum", version = "0.5" } futures-util = "0.3" -hyper = "0.14" tokio = { version = "1.0", features = ["macros"] } diff --git a/axum-core/src/body.rs b/axum-core/src/body.rs index 9f25408936..804ef0630b 100644 --- a/axum-core/src/body.rs +++ b/axum-core/src/body.rs @@ -3,7 +3,10 @@ use crate::{BoxError, Error}; use bytes::Bytes; use bytes::{Buf, BufMut}; -use http_body::Body; +use http_body::Body as _; + +#[doc(no_inline)] +pub use hyper::Body; /// A boxed [`Body`] trait object. /// @@ -55,7 +58,7 @@ where // THE SOFTWARE. pub(crate) async fn to_bytes(body: T) -> Result where - T: Body, + T: http_body::Body, { futures_util::pin_mut!(body); diff --git a/axum-core/src/extract/mod.rs b/axum-core/src/extract/mod.rs index 2316633be5..2c31dc40f4 100644 --- a/axum-core/src/extract/mod.rs +++ b/axum-core/src/extract/mod.rs @@ -5,8 +5,9 @@ //! [`axum::extract`]: https://docs.rs/axum/latest/axum/extract/index.html use self::rejection::*; -use crate::response::IntoResponse; +use crate::{body::Body, response::IntoResponse, BoxError}; use async_trait::async_trait; +use bytes::Bytes; use http::{Extensions, HeaderMap, Method, Request, Uri, Version}; use std::convert::Infallible; @@ -60,29 +61,29 @@ mod tuple; /// [`http::Request`]: http::Request /// [`axum::extract`]: https://docs.rs/axum/latest/axum/extract/index.html #[async_trait] -pub trait FromRequest: Sized { +pub trait FromRequest: Sized { /// If the extractor fails it'll use this "rejection" type. A rejection is /// a kind of error that can be converted into a response. type Rejection: IntoResponse; /// Perform the extraction. - async fn from_request(req: &mut RequestParts) -> Result; + async fn from_request(req: &mut RequestParts) -> Result; } /// The type used with [`FromRequest`] to extract data from requests. /// /// Has several convenience methods for getting owned parts of the request. #[derive(Debug)] -pub struct RequestParts { +pub struct RequestParts { method: Method, uri: Uri, version: Version, headers: HeaderMap, extensions: Extensions, - body: Option, + body: Option, } -impl RequestParts { +impl RequestParts { /// Create a new `RequestParts`. /// /// You generally shouldn't need to construct this type yourself, unless @@ -90,7 +91,11 @@ impl RequestParts { /// [`tower::Service`]. /// /// [`tower::Service`]: https://docs.rs/tower/lastest/tower/trait.Service.html - pub fn new(req: Request) -> Self { + pub fn new(req: Request) -> Self + where + B: http_body::Body + Send + 'static, + B::Error: Into, + { let ( http::request::Parts { method, @@ -109,7 +114,7 @@ impl RequestParts { version, headers, extensions, - body: Some(body), + body: Some(Body::wrap_body(body)), } } @@ -141,7 +146,10 @@ impl RequestParts { /// } /// } /// ``` - pub async fn extract>(&mut self) -> Result { + pub async fn extract(&mut self) -> Result + where + E: FromRequest, + { E::from_request(self).await } @@ -151,7 +159,7 @@ impl RequestParts { /// been called. /// /// [`take_body`]: RequestParts::take_body - pub fn try_into_request(self) -> Result, BodyAlreadyExtracted> { + pub fn try_into_request(self) -> Result, BodyAlreadyExtracted> { let Self { method, uri, @@ -229,7 +237,7 @@ impl RequestParts { /// Gets a reference to the request body. /// /// Returns `None` if the body has been taken by another extractor. - pub fn body(&self) -> Option<&B> { + pub fn body(&self) -> Option<&Body> { self.body.as_ref() } @@ -237,38 +245,36 @@ impl RequestParts { /// /// Returns `None` if the body has been taken by another extractor. // this returns `&mut Option` rather than `Option<&mut B>` such that users can use it to set the body. - pub fn body_mut(&mut self) -> &mut Option { + pub fn body_mut(&mut self) -> &mut Option { &mut self.body } /// Takes the body out of the request, leaving a `None` in its place. - pub fn take_body(&mut self) -> Option { + pub fn take_body(&mut self) -> Option { self.body.take() } } #[async_trait] -impl FromRequest for Option +impl FromRequest for Option where - T: FromRequest, - B: Send, + T: FromRequest, { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result, Self::Rejection> { + async fn from_request(req: &mut RequestParts) -> Result, Self::Rejection> { Ok(T::from_request(req).await.ok()) } } #[async_trait] -impl FromRequest for Result +impl FromRequest for Result where - T: FromRequest, - B: Send, + T: FromRequest, { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { Ok(T::from_request(req).await) } } diff --git a/axum-core/src/extract/rejection.rs b/axum-core/src/extract/rejection.rs index e6f53b8224..1546b171fc 100644 --- a/axum-core/src/extract/rejection.rs +++ b/axum-core/src/extract/rejection.rs @@ -45,9 +45,14 @@ impl FailedToBufferBody { where E: Into, { - match err.into().downcast::() { - Ok(err) => Self::LengthLimitError(LengthLimitError::from_err(err)), - Err(err) => Self::UnknownBodyError(UnknownBodyError::from_err(err)), + let err = err.into(); + if err + .source() + .map_or(false, |source| source.is::()) + { + Self::LengthLimitError(LengthLimitError::from_err(err)) + } else { + Self::UnknownBodyError(UnknownBodyError::from_err(err)) } } } diff --git a/axum-core/src/extract/request_parts.rs b/axum-core/src/extract/request_parts.rs index 33383a7d8d..c8cad44ba6 100644 --- a/axum-core/src/extract/request_parts.rs +++ b/axum-core/src/extract/request_parts.rs @@ -1,18 +1,15 @@ use super::{rejection::*, FromRequest, RequestParts}; -use crate::BoxError; +use crate::body::Body; use async_trait::async_trait; use bytes::Bytes; use http::{Extensions, HeaderMap, Method, Request, Uri, Version}; use std::convert::Infallible; #[async_trait] -impl FromRequest for Request -where - B: Send, -{ +impl FromRequest for Request { type Rejection = BodyAlreadyExtracted; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let req = std::mem::replace( req, RequestParts { @@ -30,37 +27,28 @@ where } #[async_trait] -impl FromRequest for Method -where - B: Send, -{ +impl FromRequest for Method { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { Ok(req.method().clone()) } } #[async_trait] -impl FromRequest for Uri -where - B: Send, -{ +impl FromRequest for Uri { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { Ok(req.uri().clone()) } } #[async_trait] -impl FromRequest for Version -where - B: Send, -{ +impl FromRequest for Version { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { Ok(req.version()) } } @@ -71,27 +59,28 @@ where /// /// [`TypedHeader`]: https://docs.rs/axum/latest/axum/extract/struct.TypedHeader.html #[async_trait] -impl FromRequest for HeaderMap -where - B: Send, -{ +impl FromRequest for HeaderMap { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { Ok(req.headers().clone()) } } #[async_trait] -impl FromRequest for Bytes -where - B: http_body::Body + Send, - B::Data: Send, - B::Error: Into, -{ +impl FromRequest for Body { + type Rejection = BodyAlreadyExtracted; + + async fn from_request(req: &mut RequestParts) -> Result { + Ok(take_body(req)?) + } +} + +#[async_trait] +impl FromRequest for Bytes { type Rejection = BytesRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let body = take_body(req)?; let bytes = crate::body::to_bytes(body) @@ -103,15 +92,10 @@ where } #[async_trait] -impl FromRequest for String -where - B: http_body::Body + Send, - B::Data: Send, - B::Error: Into, -{ +impl FromRequest for String { type Rejection = StringRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let body = take_body(req)?; let bytes = crate::body::to_bytes(body) @@ -126,13 +110,10 @@ where } #[async_trait] -impl FromRequest for http::request::Parts -where - B: Send, -{ +impl FromRequest for http::request::Parts { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let method = unwrap_infallible(Method::from_request(req).await); let uri = unwrap_infallible(Uri::from_request(req).await); let version = unwrap_infallible(Version::from_request(req).await); @@ -159,6 +140,6 @@ fn unwrap_infallible(result: Result) -> T { } } -pub(crate) fn take_body(req: &mut RequestParts) -> Result { +pub(crate) fn take_body(req: &mut RequestParts) -> Result { req.take_body().ok_or(BodyAlreadyExtracted) } diff --git a/axum-core/src/extract/tuple.rs b/axum-core/src/extract/tuple.rs index 8c781a8d3e..92d06cc7ef 100644 --- a/axum-core/src/extract/tuple.rs +++ b/axum-core/src/extract/tuple.rs @@ -4,31 +4,25 @@ use async_trait::async_trait; use std::convert::Infallible; #[async_trait] -impl FromRequest for () -where - B: Send, -{ +impl FromRequest for () { type Rejection = Infallible; - async fn from_request(_: &mut RequestParts) -> Result<(), Self::Rejection> { + async fn from_request(_: &mut RequestParts) -> Result<(), Self::Rejection> { Ok(()) } } macro_rules! impl_from_request { - () => {}; - ( $($ty:ident),* $(,)? ) => { #[async_trait] #[allow(non_snake_case)] - impl FromRequest for ($($ty,)*) + impl<$($ty,)*> FromRequest for ($($ty,)*) where - $( $ty: FromRequest + Send, )* - B: Send, + $( $ty: FromRequest + Send, )* { type Rejection = Response; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { $( let $ty = $ty::from_request(req).await.map_err(|err| err.into_response())?; )* Ok(($($ty,)*)) } diff --git a/axum-extra/src/extract/cached.rs b/axum-extra/src/extract/cached.rs index 0ada78a888..68be4daea8 100644 --- a/axum-extra/src/extract/cached.rs +++ b/axum-extra/src/extract/cached.rs @@ -88,14 +88,13 @@ pub struct Cached(pub T); struct CachedEntry(T); #[async_trait] -impl FromRequest for Cached +impl FromRequest for Cached where - B: Send, - T: FromRequest + Clone + Send + Sync + 'static, + T: FromRequest + Clone + Send + Sync + 'static, { type Rejection = T::Rejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { match Extension::>::from_request(req).await { Ok(Extension(CachedEntry(value))) => Ok(Self(value)), Err(_) => { @@ -124,7 +123,7 @@ impl DerefMut for Cached { #[cfg(test)] mod tests { use super::*; - use axum::http::Request; + use axum::{body::Body, http::Request}; use std::{ convert::Infallible, sync::atomic::{AtomicU32, Ordering}, @@ -139,19 +138,16 @@ mod tests { struct Extractor(Instant); #[async_trait] - impl FromRequest for Extractor - where - B: Send, - { + impl FromRequest for Extractor { type Rejection = Infallible; - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: &mut RequestParts) -> Result { COUNTER.fetch_add(1, Ordering::SeqCst); Ok(Self(Instant::now())) } } - let mut req = RequestParts::new(Request::new(())); + let mut req = RequestParts::new(Request::new(Body::empty())); let first = Cached::::from_request(&mut req).await.unwrap().0; assert_eq!(COUNTER.load(Ordering::SeqCst), 1); diff --git a/axum-extra/src/extract/cookie/mod.rs b/axum-extra/src/extract/cookie/mod.rs index 7bda1ea34e..4dcac390dc 100644 --- a/axum-extra/src/extract/cookie/mod.rs +++ b/axum-extra/src/extract/cookie/mod.rs @@ -88,13 +88,10 @@ pub struct CookieJar { } #[async_trait] -impl FromRequest for CookieJar -where - B: Send, -{ +impl FromRequest for CookieJar { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let mut jar = cookie_lib::CookieJar::new(); for cookie in cookies_from_request(req) { jar.add_original(cookie); @@ -103,9 +100,7 @@ where } } -fn cookies_from_request( - req: &mut RequestParts, -) -> impl Iterator> + '_ { +fn cookies_from_request(req: &mut RequestParts) -> impl Iterator> + '_ { req.headers() .get_all(COOKIE) .into_iter() @@ -226,7 +221,7 @@ mod tests { jar.remove(Cookie::named("key")) } - let app = Router::::new() + let app = Router::new() .route("/set", get(set_cookie)) .route("/get", get(get_cookie)) .route("/remove", get(remove_cookie)) @@ -294,7 +289,7 @@ mod tests { format!("{:?}", jar.get("key")) } - let app = Router::::new() + let app = Router::new() .route("/get", get(get_cookie)) .layer(Extension(Key::generate())); diff --git a/axum-extra/src/extract/cookie/private.rs b/axum-extra/src/extract/cookie/private.rs index a583a3c9a9..b55e9884f2 100644 --- a/axum-extra/src/extract/cookie/private.rs +++ b/axum-extra/src/extract/cookie/private.rs @@ -74,14 +74,13 @@ impl fmt::Debug for PrivateCookieJar { } #[async_trait] -impl FromRequest for PrivateCookieJar +impl FromRequest for PrivateCookieJar where - B: Send, K: Into + Clone + Send + Sync + 'static, { - type Rejection = as FromRequest>::Rejection; + type Rejection = as FromRequest>::Rejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let key = Extension::::from_request(req).await?.0.into(); let mut jar = cookie_lib::CookieJar::new(); diff --git a/axum-extra/src/extract/cookie/signed.rs b/axum-extra/src/extract/cookie/signed.rs index 51fb865c6e..18520ba22c 100644 --- a/axum-extra/src/extract/cookie/signed.rs +++ b/axum-extra/src/extract/cookie/signed.rs @@ -92,14 +92,13 @@ impl fmt::Debug for SignedCookieJar { } #[async_trait] -impl FromRequest for SignedCookieJar +impl FromRequest for SignedCookieJar where - B: Send, K: Into + Clone + Send + Sync + 'static, { - type Rejection = as FromRequest>::Rejection; + type Rejection = as FromRequest>::Rejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let key = Extension::::from_request(req).await?.0.into(); let mut jar = cookie_lib::CookieJar::new(); diff --git a/axum-extra/src/extract/form.rs b/axum-extra/src/extract/form.rs index bcd8c1809f..7d3eb49676 100644 --- a/axum-extra/src/extract/form.rs +++ b/axum-extra/src/extract/form.rs @@ -1,11 +1,9 @@ use axum::{ async_trait, - body::HttpBody, extract::{ rejection::{FailedToDeserializeQueryString, FormRejection, InvalidFormContentType}, FromRequest, RequestParts, }, - BoxError, }; use bytes::Bytes; use http::{header, Method}; @@ -54,16 +52,13 @@ impl Deref for Form { } #[async_trait] -impl FromRequest for Form +impl FromRequest for Form where T: DeserializeOwned, - B: HttpBody + Send, - B::Data: Send, - B::Error: Into, { type Rejection = FormRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { if req.method() == Method::GET { let query = req.uri().query().unwrap_or_default(); let value = serde_html_form::from_str(query) @@ -84,7 +79,7 @@ where } // this is duplicated in `axum/src/extract/mod.rs` -fn has_content_type(req: &RequestParts, expected_content_type: &mime::Mime) -> bool { +fn has_content_type(req: &RequestParts, expected_content_type: &mime::Mime) -> bool { let content_type = if let Some(content_type) = req.headers().get(header::CONTENT_TYPE) { content_type } else { diff --git a/axum-extra/src/extract/query.rs b/axum-extra/src/extract/query.rs index dcbcdb31fd..a2e9257ac4 100644 --- a/axum-extra/src/extract/query.rs +++ b/axum-extra/src/extract/query.rs @@ -58,14 +58,13 @@ use std::ops::Deref; pub struct Query(pub T); #[async_trait] -impl FromRequest for Query +impl FromRequest for Query where T: DeserializeOwned, - B: Send, { type Rejection = QueryRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let query = req.uri().query().unwrap_or_default(); let value = serde_html_form::from_str(query) .map_err(FailedToDeserializeQueryString::__private_new::)?; diff --git a/axum-extra/src/json_lines.rs b/axum-extra/src/json_lines.rs index 1bc8d1a0bd..8ac9fb92de 100644 --- a/axum-extra/src/json_lines.rs +++ b/axum-extra/src/json_lines.rs @@ -2,12 +2,12 @@ use axum::{ async_trait, - body::{HttpBody, StreamBody}, + body::{Body, Bytes, HttpBody, StreamBody}, extract::{rejection::BodyAlreadyExtracted, FromRequest, RequestParts}, response::{IntoResponse, Response}, BoxError, }; -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{BufMut, BytesMut}; use futures_util::stream::{BoxStream, Stream, TryStream, TryStreamExt}; use pin_project_lite::pin_project; use serde::{de::DeserializeOwned, Serialize}; @@ -98,25 +98,20 @@ impl JsonLines { } #[async_trait] -impl FromRequest for JsonLines +impl FromRequest for JsonLines where - B: HttpBody + Send + 'static, - B::Data: Into, - B::Error: Into, T: DeserializeOwned, { type Rejection = BodyAlreadyExtracted; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { // `Stream::lines` isn't a thing so we have to convert it into an `AsyncRead` // so we can call `AsyncRead::lines` and then convert it back to a `Stream` let body = req.take_body().ok_or_else(BodyAlreadyExtracted::default)?; let body = BodyStream { body }; - let stream = body - .map_ok(Into::into) - .map_err(|err| io::Error::new(io::ErrorKind::Other, err)); + let stream = body.map_err(|err| io::Error::new(io::ErrorKind::Other, err)); let read = StreamReader::new(stream); let lines_stream = LinesStream::new(read.lines()); @@ -139,29 +134,29 @@ where // like `axum::extract::BodyStream` except it doesn't box the inner body // we don't need that since we box the final stream in `Inner::Extractor` pin_project! { - struct BodyStream { + struct BodyStream { #[pin] - body: B, + body: Body, } } -impl Stream for BodyStream -where - B: HttpBody + Send + 'static, -{ - type Item = Result; +impl Stream for BodyStream { + type Item = Result; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.project().body.poll_data(cx) + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.body) + .poll_data(cx) + .map_err(axum::Error::new) } } impl Stream for JsonLines { type Item = Result; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + #[allow(warnings)] + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match self.project().inner.project() { - InnerProj::Extractor { stream } => stream.poll_next(cx), + InnerProj::Extractor { mut stream } => stream.as_mut().poll_next(cx), // `JsonLines<_, AsExtractor>` can only be constructed via `FromRequest` // which doesn't use this variant InnerProj::Response { .. } => unreachable!(), diff --git a/axum-extra/src/routing/mod.rs b/axum-extra/src/routing/mod.rs index 6298a36e5c..3059ef4d30 100644 --- a/axum-extra/src/routing/mod.rs +++ b/axum-extra/src/routing/mod.rs @@ -1,6 +1,7 @@ //! Additional types for defining routes. use axum::{ + body::Body, handler::Handler, http::Request, response::{Redirect, Response}, @@ -29,7 +30,7 @@ pub use self::typed::{FirstElementIs, TypedPath}; pub use self::spa::SpaRouter; /// Extension trait that adds additional methods to [`Router`]. -pub trait RouterExt: sealed::Sealed { +pub trait RouterExt: sealed::Sealed { /// Add a typed `GET` route to the router. /// /// The path will be inferred from the first argument to the handler function which must @@ -39,7 +40,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_get(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -52,7 +53,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_delete(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -65,7 +66,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_head(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -78,7 +79,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_options(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -91,7 +92,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_patch(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -104,7 +105,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_post(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -117,7 +118,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_put(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -130,7 +131,7 @@ pub trait RouterExt: sealed::Sealed { #[cfg(feature = "typed-routing")] fn typed_trace(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath; @@ -161,19 +162,16 @@ pub trait RouterExt: sealed::Sealed { /// ``` fn route_with_tsr(self, path: &str, service: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, Self: Sized; } -impl RouterExt for Router -where - B: axum::body::HttpBody + Send + 'static, -{ +impl RouterExt for Router { #[cfg(feature = "typed-routing")] fn typed_get(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -183,7 +181,7 @@ where #[cfg(feature = "typed-routing")] fn typed_delete(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -193,7 +191,7 @@ where #[cfg(feature = "typed-routing")] fn typed_head(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -203,7 +201,7 @@ where #[cfg(feature = "typed-routing")] fn typed_options(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -213,7 +211,7 @@ where #[cfg(feature = "typed-routing")] fn typed_patch(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -223,7 +221,7 @@ where #[cfg(feature = "typed-routing")] fn typed_post(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -233,7 +231,7 @@ where #[cfg(feature = "typed-routing")] fn typed_put(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -243,7 +241,7 @@ where #[cfg(feature = "typed-routing")] fn typed_trace(self, handler: H) -> Self where - H: Handler, + H: Handler, T: FirstElementIs

+ 'static, P: TypedPath, { @@ -252,7 +250,7 @@ where fn route_with_tsr(mut self, path: &str, service: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, Self: Sized, { @@ -276,7 +274,7 @@ where mod sealed { pub trait Sealed {} - impl Sealed for axum::Router {} + impl Sealed for axum::Router {} } #[cfg(test)] diff --git a/axum-extra/src/routing/resource.rs b/axum-extra/src/routing/resource.rs index 48fcba018c..a6796f42b2 100644 --- a/axum-extra/src/routing/resource.rs +++ b/axum-extra/src/routing/resource.rs @@ -47,15 +47,12 @@ use tower_service::Service; /// let app = Router::new().merge(users); /// # let _: Router = app; /// ``` -pub struct Resource { +pub struct Resource { pub(crate) name: String, - pub(crate) router: Router, + pub(crate) router: Router, } -impl Resource -where - B: axum::body::HttpBody + Send + 'static, -{ +impl Resource { /// Create a `Resource` with the given name. /// /// All routes will be nested at `/{resource_name}`. @@ -69,7 +66,7 @@ where /// Add a handler at `GET /{resource_name}`. pub fn index(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = self.index_create_path(); @@ -79,7 +76,7 @@ where /// Add a handler at `POST /{resource_name}`. pub fn create(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = self.index_create_path(); @@ -89,7 +86,7 @@ where /// Add a handler at `GET /{resource_name}/new`. pub fn new(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = format!("/{}/new", self.name); @@ -99,7 +96,7 @@ where /// Add a handler at `GET /{resource_name}/:{resource_name}_id`. pub fn show(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = self.show_update_destroy_path(); @@ -109,7 +106,7 @@ where /// Add a handler at `GET /{resource_name}/:{resource_name}_id/edit`. pub fn edit(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = format!("/{0}/:{0}_id/edit", self.name); @@ -119,7 +116,7 @@ where /// Add a handler at `PUT or PATCH /resource_name/:{resource_name}_id`. pub fn update(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = self.show_update_destroy_path(); @@ -129,7 +126,7 @@ where /// Add a handler at `DELETE /{resource_name}/:{resource_name}_id`. pub fn destroy(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { let path = self.show_update_destroy_path(); @@ -141,7 +138,7 @@ where /// The routes will be nested at `/{resource_name}/:{resource_name}_id`. pub fn nest(mut self, svc: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, { let path = self.show_update_destroy_path(); @@ -154,7 +151,7 @@ where /// The routes will be nested at `/{resource_name}`. pub fn nest_collection(mut self, svc: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, { let path = self.index_create_path(); @@ -172,7 +169,7 @@ where fn route(mut self, path: &str, svc: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, { self.router = self.router.route(path, svc); @@ -180,13 +177,13 @@ where } } -impl From> for Router { - fn from(resource: Resource) -> Self { +impl From for Router { + fn from(resource: Resource) -> Self { resource.router } } -impl fmt::Debug for Resource { +impl fmt::Debug for Resource { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Resource") .field("name", &self.name) @@ -199,7 +196,7 @@ impl fmt::Debug for Resource { mod tests { #[allow(unused_imports)] use super::*; - use axum::{extract::Path, http::Method, Router}; + use axum::{body::Body, extract::Path, http::Method, Router}; use tower::ServiceExt; #[tokio::test] @@ -220,65 +217,60 @@ mod tests { Router::new().route("/featured", get(|| async move { "users#featured" })), ); - let mut app = Router::new().merge(users); + let app = Router::new().merge(users); - assert_eq!( - call_route(&mut app, Method::GET, "/users").await, - "users#index" - ); + assert_eq!(call_route(&app, Method::GET, "/users").await, "users#index"); assert_eq!( - call_route(&mut app, Method::POST, "/users").await, + call_route(&app, Method::POST, "/users").await, "users#create" ); assert_eq!( - call_route(&mut app, Method::GET, "/users/new").await, + call_route(&app, Method::GET, "/users/new").await, "users#new" ); assert_eq!( - call_route(&mut app, Method::GET, "/users/1").await, + call_route(&app, Method::GET, "/users/1").await, "users#show id=1" ); assert_eq!( - call_route(&mut app, Method::GET, "/users/1/edit").await, + call_route(&app, Method::GET, "/users/1/edit").await, "users#edit id=1" ); assert_eq!( - call_route(&mut app, Method::PATCH, "/users/1").await, + call_route(&app, Method::PATCH, "/users/1").await, "users#update id=1" ); assert_eq!( - call_route(&mut app, Method::PUT, "/users/1").await, + call_route(&app, Method::PUT, "/users/1").await, "users#update id=1" ); assert_eq!( - call_route(&mut app, Method::DELETE, "/users/1").await, + call_route(&app, Method::DELETE, "/users/1").await, "users#destroy id=1" ); assert_eq!( - call_route(&mut app, Method::GET, "/users/1/tweets").await, + call_route(&app, Method::GET, "/users/1/tweets").await, "users#tweets id=1" ); assert_eq!( - call_route(&mut app, Method::GET, "/users/featured").await, + call_route(&app, Method::GET, "/users/featured").await, "users#featured" ); } - async fn call_route(app: &mut Router, method: Method, uri: &str) -> String { + async fn call_route(app: &Router, method: Method, uri: &str) -> String { let res = app - .ready() - .await - .unwrap() - .call( + .clone() + .oneshot( Request::builder() .method(method) .uri(uri) diff --git a/axum-extra/src/routing/spa.rs b/axum-extra/src/routing/spa.rs index 594b15c237..fc05e5a0fa 100644 --- a/axum-extra/src/routing/spa.rs +++ b/axum-extra/src/routing/spa.rs @@ -1,5 +1,5 @@ use axum::{ - body::{Body, HttpBody}, + body::Body, error_handling::HandleError, response::Response, routing::{get_service, Route}, @@ -50,10 +50,10 @@ use tower_service::Service; /// - `GET /some/other/path` will serve `index.html` since there isn't another /// route for it /// - `GET /api/foo` will serve the `api_foo` handler function -pub struct SpaRouter Ready> { +pub struct SpaRouter Ready> { paths: Arc, handle_error: F, - _marker: PhantomData (B, T)>, + _marker: PhantomData T>, } #[derive(Debug)] @@ -63,7 +63,7 @@ struct Paths { index_file: PathBuf, } -impl SpaRouter Ready> { +impl SpaRouter<(), fn(io::Error) -> Ready> { /// Create a new `SpaRouter`. /// /// Assets will be served at `GET /{serve_assets_at}` from the directory at `assets_dir`. @@ -86,7 +86,7 @@ impl SpaRouter Ready> { } } -impl SpaRouter { +impl SpaRouter { /// Set the path to the index file. /// /// `path` must be relative to `assets_dir` passed to [`SpaRouter::new`]. @@ -138,7 +138,7 @@ impl SpaRouter { /// let app = Router::new().merge(spa); /// # let _: Router = app; /// ``` - pub fn handle_error(self, f: F2) -> SpaRouter { + pub fn handle_error(self, f: F2) -> SpaRouter { SpaRouter { paths: self.paths, handle_error: f, @@ -147,16 +147,15 @@ impl SpaRouter { } } -impl From> for Router +impl From> for Router where F: Clone + Send + 'static, - HandleError, F, T>: - Service, Response = Response, Error = Infallible>, - , F, T> as Service>>::Future: Send, - B: HttpBody + Send + 'static, + HandleError, F, T>: + Service, Response = Response, Error = Infallible>, + , F, T> as Service>>::Future: Send, T: 'static, { - fn from(spa: SpaRouter) -> Self { + fn from(spa: SpaRouter) -> Self { let assets_service = get_service(ServeDir::new(&spa.paths.assets_dir)) .handle_error(spa.handle_error.clone()); @@ -168,7 +167,7 @@ where } } -impl fmt::Debug for SpaRouter { +impl fmt::Debug for SpaRouter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { paths, @@ -179,7 +178,6 @@ impl fmt::Debug for SpaRouter { f.debug_struct("SpaRouter") .field("paths", &paths) .field("handle_error", &format_args!("{}", type_name::())) - .field("request_body_type", &format_args!("{}", type_name::())) .field( "extractor_input_type", &format_args!("{}", type_name::()), @@ -188,7 +186,7 @@ impl fmt::Debug for SpaRouter { } } -impl Clone for SpaRouter +impl Clone for SpaRouter where F: Clone, { @@ -264,6 +262,6 @@ mod tests { let spa = SpaRouter::new("/assets", "test_files").handle_error(handle_error); - Router::::new().merge(spa); + Router::new().merge(spa); } } diff --git a/axum-macros/src/debug_handler.rs b/axum-macros/src/debug_handler.rs index 7945e8bb84..a1622debd0 100644 --- a/axum-macros/src/debug_handler.rs +++ b/axum-macros/src/debug_handler.rs @@ -1,14 +1,14 @@ use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned}; -use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, Token, Type}; +use syn::{parse::Parse, spanned::Spanned, FnArg, ItemFn, Type}; -pub(crate) fn expand(attr: Attrs, item_fn: ItemFn) -> TokenStream { +pub(crate) fn expand(_attr: Attrs, item_fn: ItemFn) -> TokenStream { let check_extractor_count = check_extractor_count(&item_fn); let check_request_last_extractor = check_request_last_extractor(&item_fn); let check_path_extractor = check_path_extractor(&item_fn); let check_multiple_body_extractors = check_multiple_body_extractors(&item_fn); - let check_inputs_impls_from_request = check_inputs_impls_from_request(&item_fn, &attr.body_ty); + let check_inputs_impls_from_request = check_inputs_impls_from_request(&item_fn); let check_output_impls_into_response = check_output_impls_into_response(&item_fn); let check_future_send = check_future_send(&item_fn); @@ -24,29 +24,11 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn) -> TokenStream { } } -pub(crate) struct Attrs { - body_ty: Type, -} +pub(crate) struct Attrs {} impl Parse for Attrs { - fn parse(input: syn::parse::ParseStream) -> syn::Result { - let mut body_ty = None; - - while !input.is_empty() { - let ident = input.parse::()?; - if ident == "body" { - input.parse::()?; - body_ty = Some(input.parse()?); - } else { - return Err(syn::Error::new_spanned(ident, "unknown argument")); - } - - let _ = input.parse::(); - } - - let body_ty = body_ty.unwrap_or_else(|| syn::parse_quote!(axum::body::Body)); - - Ok(Self { body_ty }) + fn parse(_input: syn::parse::ParseStream) -> syn::Result { + Ok(Self {}) } } @@ -152,7 +134,7 @@ fn check_multiple_body_extractors(item_fn: &ItemFn) -> TokenStream { } } -fn check_inputs_impls_from_request(item_fn: &ItemFn, body_ty: &Type) -> TokenStream { +fn check_inputs_impls_from_request(item_fn: &ItemFn) -> TokenStream { if !item_fn.sig.generics.params.is_empty() { return syn::Error::new_spanned( &item_fn.sig.generics, @@ -196,7 +178,7 @@ fn check_inputs_impls_from_request(item_fn: &ItemFn, body_ty: &Type) -> TokenStr #[allow(warnings)] fn #name() where - #ty: ::axum::extract::FromRequest<#body_ty> + Send, + #ty: ::axum::extract::FromRequest + Send, {} } }) diff --git a/axum-macros/src/from_request.rs b/axum-macros/src/from_request.rs index 76634ee9b2..f7938d46f5 100644 --- a/axum-macros/src/from_request.rs +++ b/axum-macros/src/from_request.rs @@ -106,16 +106,11 @@ fn impl_struct_by_extracting_each_field( Ok(quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident - where - B: ::axum::body::HttpBody + ::std::marker::Send + 'static, - B::Data: ::std::marker::Send, - B::Error: ::std::convert::Into<::axum::BoxError>, - { + impl ::axum::extract::FromRequest for #ident { type Rejection = #rejection_ident; async fn from_request( - req: &mut ::axum::extract::RequestParts, + req: &mut ::axum::extract::RequestParts, ) -> ::std::result::Result { ::std::result::Result::Ok(Self { #(#extract_fields)* @@ -301,7 +296,7 @@ fn extract_each_field_rejection( Ok(quote_spanned! {ty_span=> #[allow(non_camel_case_types)] - #variant_name(<#extractor_ty as ::axum::extract::FromRequest<::axum::body::Body>>::Rejection), + #variant_name(<#extractor_ty as ::axum::extract::FromRequest>::Rejection), }) }) .collect::>>()?; @@ -485,18 +480,13 @@ fn impl_struct_by_extracting_all_at_once( Ok(quote_spanned! {path_span=> #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident - where - B: ::axum::body::HttpBody + ::std::marker::Send + 'static, - B::Data: ::std::marker::Send, - B::Error: ::std::convert::Into<::axum::BoxError>, - { - type Rejection = <#path as ::axum::extract::FromRequest>::Rejection; + impl ::axum::extract::FromRequest for #ident { + type Rejection = <#path as ::axum::extract::FromRequest>::Rejection; async fn from_request( - req: &mut ::axum::extract::RequestParts, + req: &mut ::axum::extract::RequestParts, ) -> ::std::result::Result { - ::axum::extract::FromRequest::::from_request(req) + ::axum::extract::FromRequest::from_request(req) .await .map(|#path(inner)| inner) } @@ -540,18 +530,13 @@ fn impl_enum_by_extracting_all_at_once( Ok(quote_spanned! {path_span=> #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident - where - B: ::axum::body::HttpBody + ::std::marker::Send + 'static, - B::Data: ::std::marker::Send, - B::Error: ::std::convert::Into<::axum::BoxError>, - { - type Rejection = <#path as ::axum::extract::FromRequest>::Rejection; + impl ::axum::extract::FromRequest for #ident { + type Rejection = <#path as ::axum::extract::FromRequest>::Rejection; async fn from_request( - req: &mut ::axum::extract::RequestParts, + req: &mut ::axum::extract::RequestParts, ) -> ::std::result::Result { - ::axum::extract::FromRequest::::from_request(req) + ::axum::extract::FromRequest::from_request(req) .await .map(|#path(inner)| inner) } diff --git a/axum-macros/src/lib.rs b/axum-macros/src/lib.rs index a44a14db32..7a0c2ca781 100644 --- a/axum-macros/src/lib.rs +++ b/axum-macros/src/lib.rs @@ -354,22 +354,6 @@ pub fn derive_from_request(item: TokenStream) -> TokenStream { /// } /// ``` /// -/// # Changing request body type -/// -/// By default `#[debug_handler]` assumes your request body type is `axum::body::Body`. This will -/// work for most extractors but, for example, it wont work for `Request`, -/// which only implements `FromRequest` and _not_ `FromRequest`. -/// -/// To work around that the request body type can be customized like so: -/// -/// ``` -/// use axum::{body::BoxBody, http::Request}; -/// # use axum_macros::debug_handler; -/// -/// #[debug_handler(body = BoxBody)] -/// async fn handler(request: Request) {} -/// ``` -/// /// # Performance /// /// This macro has no effect when compiled with the release profile. (eg. `cargo build --release`) diff --git a/axum-macros/src/typed_path.rs b/axum-macros/src/typed_path.rs index a765437198..98aeb1dec9 100644 --- a/axum-macros/src/typed_path.rs +++ b/axum-macros/src/typed_path.rs @@ -127,13 +127,10 @@ fn expand_named_fields( let from_request_impl = quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident - where - B: Send, - { + impl ::axum::extract::FromRequest for #ident { type Rejection = #rejection_assoc_type; - async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { + async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { ::axum::extract::Path::from_request(req) .await .map(|path| path.0) @@ -229,13 +226,10 @@ fn expand_unnamed_fields( let from_request_impl = quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident - where - B: Send, - { + impl ::axum::extract::FromRequest for #ident { type Rejection = #rejection_assoc_type; - async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { + async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { ::axum::extract::Path::from_request(req) .await .map(|path| path.0) @@ -310,13 +304,10 @@ fn expand_unit_fields( let from_request_impl = quote! { #[::axum::async_trait] #[automatically_derived] - impl ::axum::extract::FromRequest for #ident - where - B: Send, - { + impl ::axum::extract::FromRequest for #ident { type Rejection = #rejection_assoc_type; - async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { + async fn from_request(req: &mut ::axum::extract::RequestParts) -> ::std::result::Result { if req.uri().path() == ::PATH { Ok(Self) } else { @@ -387,7 +378,7 @@ enum Segment { fn path_rejection() -> TokenStream { quote! { - <::axum::extract::Path as ::axum::extract::FromRequest>::Rejection + <::axum::extract::Path as ::axum::extract::FromRequest>::Rejection } } diff --git a/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr index 078b2b0371..d54cb460e5 100644 --- a/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr +++ b/axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr @@ -1,10 +1,10 @@ -error[E0277]: the trait bound `bool: FromRequest` is not satisfied +error[E0277]: the trait bound `bool: FromRequest` is not satisfied --> tests/debug_handler/fail/argument_not_extractor.rs:4:23 | 4 | async fn handler(foo: bool) {} - | ^^^^ the trait `FromRequest` is not implemented for `bool` + | ^^^^ the trait `FromRequest` is not implemented for `bool` | - = help: the following other types implement trait `FromRequest`: + = help: the following other types implement trait `FromRequest`: () (T1, T2) (T1, T2, T3) diff --git a/axum-macros/tests/debug_handler/fail/extract_self_mut.rs b/axum-macros/tests/debug_handler/fail/extract_self_mut.rs index 01eb636bc0..e92644af7e 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_mut.rs +++ b/axum-macros/tests/debug_handler/fail/extract_self_mut.rs @@ -7,13 +7,10 @@ use axum_macros::debug_handler; struct A; #[async_trait] -impl FromRequest for A -where - B: Send + 'static, -{ +impl FromRequest for A { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: &mut RequestParts) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr b/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr index 595786bf4e..3421cb1953 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr +++ b/axum-macros/tests/debug_handler/fail/extract_self_mut.stderr @@ -1,5 +1,5 @@ error: Handlers must only take owned values - --> tests/debug_handler/fail/extract_self_mut.rs:23:22 + --> tests/debug_handler/fail/extract_self_mut.rs:20:22 | -23 | async fn handler(&mut self) {} +20 | async fn handler(&mut self) {} | ^^^^^^^^^ diff --git a/axum-macros/tests/debug_handler/fail/extract_self_ref.rs b/axum-macros/tests/debug_handler/fail/extract_self_ref.rs index d64732cdcc..49769a94e9 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_ref.rs +++ b/axum-macros/tests/debug_handler/fail/extract_self_ref.rs @@ -7,13 +7,10 @@ use axum_macros::debug_handler; struct A; #[async_trait] -impl FromRequest for A -where - B: Send + 'static, -{ +impl FromRequest for A { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: &mut RequestParts) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr b/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr index 4c0b4950c7..610dfa6adc 100644 --- a/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr +++ b/axum-macros/tests/debug_handler/fail/extract_self_ref.stderr @@ -1,5 +1,5 @@ error: Handlers must only take owned values - --> tests/debug_handler/fail/extract_self_ref.rs:23:22 + --> tests/debug_handler/fail/extract_self_ref.rs:20:22 | -23 | async fn handler(&self) {} +20 | async fn handler(&self) {} | ^^^^^ diff --git a/axum-macros/tests/debug_handler/fail/invalid_attrs.stderr b/axum-macros/tests/debug_handler/fail/invalid_attrs.stderr index 20705a0db6..da104e8253 100644 --- a/axum-macros/tests/debug_handler/fail/invalid_attrs.stderr +++ b/axum-macros/tests/debug_handler/fail/invalid_attrs.stderr @@ -1,4 +1,4 @@ -error: unknown argument +error: unexpected token --> tests/debug_handler/fail/invalid_attrs.rs:3:17 | 3 | #[debug_handler(foo)] diff --git a/axum-macros/tests/debug_handler/fail/request_not_last.rs b/axum-macros/tests/debug_handler/fail/request_not_last.rs index 153d35ef3f..ff58b2a3f1 100644 --- a/axum-macros/tests/debug_handler/fail/request_not_last.rs +++ b/axum-macros/tests/debug_handler/fail/request_not_last.rs @@ -1,4 +1,4 @@ -use axum::{body::Body, extract::Extension, http::Request}; +use axum::{extract::Extension, body::Body, http::Request}; use axum_macros::debug_handler; #[debug_handler] diff --git a/axum-macros/tests/debug_handler/pass/different_request_body_type.rs b/axum-macros/tests/debug_handler/pass/different_request_body_type.rs deleted file mode 100644 index 715e5aec19..0000000000 --- a/axum-macros/tests/debug_handler/pass/different_request_body_type.rs +++ /dev/null @@ -1,10 +0,0 @@ -use axum::{body::BoxBody, http::Request}; -use axum_macros::debug_handler; - -#[debug_handler(body = BoxBody)] -async fn handler(_: Request) {} - -#[debug_handler(body = axum::body::BoxBody,)] -async fn handler_with_trailing_comma_and_type_path(_: Request) {} - -fn main() {} diff --git a/axum-macros/tests/debug_handler/pass/request_last.rs b/axum-macros/tests/debug_handler/pass/request_last.rs index bbfb53d28e..1572651e63 100644 --- a/axum-macros/tests/debug_handler/pass/request_last.rs +++ b/axum-macros/tests/debug_handler/pass/request_last.rs @@ -1,4 +1,4 @@ -use axum::{body::Body, extract::Extension, http::Request}; +use axum::{extract::Extension, body::Body, http::Request}; use axum_macros::debug_handler; #[debug_handler] diff --git a/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs b/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs index 81269a9cb2..7620517c78 100644 --- a/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs +++ b/axum-macros/tests/debug_handler/pass/result_impl_into_response.rs @@ -120,13 +120,10 @@ impl A { } #[async_trait] -impl FromRequest for A -where - B: Send + 'static, -{ +impl FromRequest for A { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: &mut RequestParts) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/debug_handler/pass/self_receiver.rs b/axum-macros/tests/debug_handler/pass/self_receiver.rs index f22ccc08cd..b1ae239196 100644 --- a/axum-macros/tests/debug_handler/pass/self_receiver.rs +++ b/axum-macros/tests/debug_handler/pass/self_receiver.rs @@ -7,13 +7,10 @@ use axum_macros::debug_handler; struct A; #[async_trait] -impl FromRequest for A -where - B: Send + 'static, -{ +impl FromRequest for A { type Rejection = (); - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: &mut RequestParts) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/from_request/pass/container.rs b/axum-macros/tests/from_request/pass/container.rs index a6732527e4..1438d6839c 100644 --- a/axum-macros/tests/from_request/pass/container.rs +++ b/axum-macros/tests/from_request/pass/container.rs @@ -1,7 +1,4 @@ -use axum::{ - body::Body, - extract::{rejection::JsonRejection, FromRequest, Json}, -}; +use axum::extract::{rejection::JsonRejection, FromRequest, Json}; use axum_macros::FromRequest; use serde::Deserialize; @@ -15,7 +12,7 @@ struct Extractor { fn assert_from_request() where - Extractor: FromRequest, + Extractor: FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/derive_opt_out.rs b/axum-macros/tests/from_request/pass/derive_opt_out.rs index 0bf24c7389..d549b76b95 100644 --- a/axum-macros/tests/from_request/pass/derive_opt_out.rs +++ b/axum-macros/tests/from_request/pass/derive_opt_out.rs @@ -14,13 +14,10 @@ struct Extractor { struct OtherExtractor; #[async_trait] -impl FromRequest for OtherExtractor -where - B: Send + 'static, -{ +impl FromRequest for OtherExtractor { type Rejection = OtherExtractorRejection; - async fn from_request(_req: &mut RequestParts) -> Result { + async fn from_request(_req: &mut RequestParts) -> Result { unimplemented!() } } diff --git a/axum-macros/tests/from_request/pass/empty_named.rs b/axum-macros/tests/from_request/pass/empty_named.rs index 2cc5dda8b6..4e7eb3c917 100644 --- a/axum-macros/tests/from_request/pass/empty_named.rs +++ b/axum-macros/tests/from_request/pass/empty_named.rs @@ -5,7 +5,7 @@ struct Extractor {} fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/empty_tuple.rs b/axum-macros/tests/from_request/pass/empty_tuple.rs index bbb525fa1b..f088672366 100644 --- a/axum-macros/tests/from_request/pass/empty_tuple.rs +++ b/axum-macros/tests/from_request/pass/empty_tuple.rs @@ -5,7 +5,7 @@ struct Extractor(); fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/enum_via.rs b/axum-macros/tests/from_request/pass/enum_via.rs index d6ba90e277..dee1549d6f 100644 --- a/axum-macros/tests/from_request/pass/enum_via.rs +++ b/axum-macros/tests/from_request/pass/enum_via.rs @@ -1,4 +1,4 @@ -use axum::{body::Body, routing::get, Extension, Router}; +use axum::{routing::get, Extension, Router}; use axum_macros::FromRequest; #[derive(FromRequest, Clone)] @@ -8,5 +8,5 @@ enum Extractor {} async fn foo(_: Extractor) {} fn main() { - Router::::new().route("/", get(foo)); + Router::new().route("/", get(foo)); } diff --git a/axum-macros/tests/from_request/pass/named.rs b/axum-macros/tests/from_request/pass/named.rs index 4ee40a0447..04cc925070 100644 --- a/axum-macros/tests/from_request/pass/named.rs +++ b/axum-macros/tests/from_request/pass/named.rs @@ -1,5 +1,4 @@ use axum::{ - body::Body, extract::{FromRequest, TypedHeader, rejection::{TypedHeaderRejection, StringRejection}}, headers::{self, UserAgent}, }; @@ -18,7 +17,7 @@ struct Extractor { fn assert_from_request() where - Extractor: FromRequest, + Extractor: FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/named_via.rs b/axum-macros/tests/from_request/pass/named_via.rs index fc03b8c0fb..449421d2d7 100644 --- a/axum-macros/tests/from_request/pass/named_via.rs +++ b/axum-macros/tests/from_request/pass/named_via.rs @@ -1,5 +1,4 @@ use axum::{ - body::Body, extract::{ rejection::{ExtensionRejection, TypedHeaderRejection}, Extension, FromRequest, TypedHeader, @@ -25,7 +24,7 @@ struct Extractor { fn assert_from_request() where - Extractor: FromRequest, + Extractor: FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/tuple.rs b/axum-macros/tests/from_request/pass/tuple.rs index 9786285223..efc9c24ebd 100644 --- a/axum-macros/tests/from_request/pass/tuple.rs +++ b/axum-macros/tests/from_request/pass/tuple.rs @@ -5,7 +5,7 @@ struct Extractor(axum::http::HeaderMap, String); fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/tuple_same_type_twice.rs b/axum-macros/tests/from_request/pass/tuple_same_type_twice.rs index 0434bb29f3..e1c13380ef 100644 --- a/axum-macros/tests/from_request/pass/tuple_same_type_twice.rs +++ b/axum-macros/tests/from_request/pass/tuple_same_type_twice.rs @@ -13,7 +13,7 @@ struct Payload {} fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs b/axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs index df7761eab9..5c084aed43 100644 --- a/axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs +++ b/axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs @@ -27,7 +27,7 @@ struct Payload {} fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/tuple_via.rs b/axum-macros/tests/from_request/pass/tuple_via.rs index dde9887771..fa4a20714a 100644 --- a/axum-macros/tests/from_request/pass/tuple_via.rs +++ b/axum-macros/tests/from_request/pass/tuple_via.rs @@ -9,7 +9,7 @@ struct State; fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/from_request/pass/unit.rs b/axum-macros/tests/from_request/pass/unit.rs index 57f774d143..1a7bfd070f 100644 --- a/axum-macros/tests/from_request/pass/unit.rs +++ b/axum-macros/tests/from_request/pass/unit.rs @@ -5,7 +5,7 @@ struct Extractor; fn assert_from_request() where - Extractor: axum::extract::FromRequest, + Extractor: axum::extract::FromRequest, { } diff --git a/axum-macros/tests/typed_path/fail/not_deserialize.stderr b/axum-macros/tests/typed_path/fail/not_deserialize.stderr index 7581b3997c..c817795b5c 100644 --- a/axum-macros/tests/typed_path/fail/not_deserialize.stderr +++ b/axum-macros/tests/typed_path/fail/not_deserialize.stderr @@ -15,5 +15,5 @@ error[E0277]: the trait bound `for<'de> MyPath: serde::de::Deserialize<'de>` is (T0, T1, T2, T3) and 138 others = note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `MyPath` - = note: required because of the requirements on the impl of `FromRequest` for `axum::extract::Path` + = note: required because of the requirements on the impl of `FromRequest` for `axum::extract::Path` = note: this error originates in the derive macro `TypedPath` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/axum-macros/tests/typed_path/pass/customize_rejection.rs b/axum-macros/tests/typed_path/pass/customize_rejection.rs index 41aa7e614e..a8be58876e 100644 --- a/axum-macros/tests/typed_path/pass/customize_rejection.rs +++ b/axum-macros/tests/typed_path/pass/customize_rejection.rs @@ -40,7 +40,7 @@ impl Default for MyRejection { } fn main() { - axum::Router::::new() + axum::Router::new() .typed_get(|_: Result| async {}) .typed_post(|_: Result| async {}) .typed_put(|_: Result| async {}); diff --git a/axum-macros/tests/typed_path/pass/named_fields_struct.rs b/axum-macros/tests/typed_path/pass/named_fields_struct.rs index 6942bd3394..d19b0e60c5 100644 --- a/axum-macros/tests/typed_path/pass/named_fields_struct.rs +++ b/axum-macros/tests/typed_path/pass/named_fields_struct.rs @@ -9,7 +9,7 @@ struct MyPath { } fn main() { - axum::Router::::new().route("/", axum::routing::get(|_: MyPath| async {})); + axum::Router::new().route("/", axum::routing::get(|_: MyPath| async {})); assert_eq!(MyPath::PATH, "/users/:user_id/teams/:team_id"); assert_eq!( diff --git a/axum-macros/tests/typed_path/pass/option_result.rs b/axum-macros/tests/typed_path/pass/option_result.rs index d89dea2dd5..cfe160100d 100644 --- a/axum-macros/tests/typed_path/pass/option_result.rs +++ b/axum-macros/tests/typed_path/pass/option_result.rs @@ -20,7 +20,7 @@ struct UsersIndex; async fn result_handler_unit_struct(_: Result) {} fn main() { - axum::Router::::new() + axum::Router::new() .typed_get(option_handler) .typed_post(result_handler) .typed_post(result_handler_unit_struct); diff --git a/axum-macros/tests/typed_path/pass/tuple_struct.rs b/axum-macros/tests/typed_path/pass/tuple_struct.rs index 5e3d27ff40..1d5bad1a26 100644 --- a/axum-macros/tests/typed_path/pass/tuple_struct.rs +++ b/axum-macros/tests/typed_path/pass/tuple_struct.rs @@ -8,7 +8,7 @@ pub type Result = std::result::Result; struct MyPath(u32, u32); fn main() { - axum::Router::::new().route("/", axum::routing::get(|_: MyPath| async {})); + axum::Router::new().route("/", axum::routing::get(|_: MyPath| async {})); assert_eq!(MyPath::PATH, "/users/:user_id/teams/:team_id"); assert_eq!(format!("{}", MyPath(1, 2)), "/users/1/teams/2"); diff --git a/axum-macros/tests/typed_path/pass/unit_struct.rs b/axum-macros/tests/typed_path/pass/unit_struct.rs index 9b6a0f6e39..25b090d38d 100644 --- a/axum-macros/tests/typed_path/pass/unit_struct.rs +++ b/axum-macros/tests/typed_path/pass/unit_struct.rs @@ -5,7 +5,7 @@ use axum_extra::routing::TypedPath; struct MyPath; fn main() { - axum::Router::::new() + axum::Router::new() .route("/", axum::routing::get(|_: MyPath| async {})); assert_eq!(MyPath::PATH, "/users"); diff --git a/axum-macros/tests/typed_path/pass/wildcards.rs b/axum-macros/tests/typed_path/pass/wildcards.rs index 0c9155f71d..e10dd9b013 100644 --- a/axum-macros/tests/typed_path/pass/wildcards.rs +++ b/axum-macros/tests/typed_path/pass/wildcards.rs @@ -8,5 +8,5 @@ struct MyPath { } fn main() { - axum::Router::::new().typed_get(|_: MyPath| async {}); + axum::Router::new().typed_get(|_: MyPath| async {}); } diff --git a/axum/src/error_handling/mod.rs b/axum/src/error_handling/mod.rs index e0027eed33..0266e8b97a 100644 --- a/axum/src/error_handling/mod.rs +++ b/axum/src/error_handling/mod.rs @@ -1,7 +1,7 @@ #![doc = include_str!("../docs/error_handling.md")] use crate::{ - body::{boxed, Bytes, HttpBody}, + body::{boxed, Body, Bytes, HttpBody}, extract::{FromRequest, RequestParts}, http::{Request, StatusCode}, response::{IntoResponse, Response}, @@ -114,15 +114,14 @@ where } } -impl Service> for HandleError +impl Service> for HandleError where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Error: Send, S::Future: Send, F: FnOnce(S::Error) -> Fut + Clone + Send + 'static, Fut: Future + Send, Res: IntoResponse, - ReqBody: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { @@ -134,7 +133,7 @@ where Poll::Ready(Ok(())) } - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { let f = self.f.clone(); let clone = self.inner.clone(); @@ -154,17 +153,16 @@ where #[allow(unused_macros)] macro_rules! impl_service { ( $($ty:ident),* $(,)? ) => { - impl Service> + impl Service> for HandleError where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Error: Send, S::Future: Send, F: FnOnce($($ty),*, S::Error) -> Fut + Clone + Send + 'static, Fut: Future + Send, Res: IntoResponse, - $( $ty: FromRequest + Send,)* - ReqBody: Send + 'static, + $( $ty: FromRequest + Send,)* ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { @@ -178,7 +176,7 @@ macro_rules! impl_service { } #[allow(non_snake_case)] - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { let f = self.f.clone(); let clone = self.inner.clone(); diff --git a/axum/src/extension.rs b/axum/src/extension.rs index 390f29e031..78527e1d64 100644 --- a/axum/src/extension.rs +++ b/axum/src/extension.rs @@ -73,14 +73,13 @@ use tower_service::Service; pub struct Extension(pub T); #[async_trait] -impl FromRequest for Extension +impl FromRequest for Extension where T: Clone + Send + Sync + 'static, - B: Send, { type Rejection = ExtensionRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let value = req .extensions() .get::() diff --git a/axum/src/extract/connect_info.rs b/axum/src/extract/connect_info.rs index 8363a25ebf..1ee0e86447 100644 --- a/axum/src/extract/connect_info.rs +++ b/axum/src/extract/connect_info.rs @@ -128,14 +128,13 @@ opaque_future! { pub struct ConnectInfo(pub T); #[async_trait] -impl FromRequest for ConnectInfo +impl FromRequest for ConnectInfo where - B: Send, T: Clone + Send + Sync + 'static, { - type Rejection = as FromRequest>::Rejection; + type Rejection = as FromRequest>::Rejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let Extension(connect_info) = Extension::::from_request(req).await?; Ok(connect_info) } diff --git a/axum/src/extract/content_length_limit.rs b/axum/src/extract/content_length_limit.rs index 62148a8ea7..85d8785fa3 100644 --- a/axum/src/extract/content_length_limit.rs +++ b/axum/src/extract/content_length_limit.rs @@ -36,15 +36,14 @@ use std::ops::Deref; pub struct ContentLengthLimit(pub T); #[async_trait] -impl FromRequest for ContentLengthLimit +impl FromRequest for ContentLengthLimit where - T: FromRequest, + T: FromRequest, T::Rejection: IntoResponse, - B: Send, { type Rejection = ContentLengthLimitRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let content_length = req .headers() .get(http::header::CONTENT_LENGTH) diff --git a/axum/src/extract/host.rs b/axum/src/extract/host.rs index 85ab8a9dcd..8fb0890b22 100644 --- a/axum/src/extract/host.rs +++ b/axum/src/extract/host.rs @@ -21,13 +21,10 @@ const X_FORWARDED_HOST_HEADER_KEY: &str = "X-Forwarded-Host"; pub struct Host(pub String); #[async_trait] -impl FromRequest for Host -where - B: Send, -{ +impl FromRequest for Host { type Rejection = HostRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { if let Some(host) = parse_forwarded(req.headers()) { return Ok(Host(host.to_owned())); } diff --git a/axum/src/extract/matched_path.rs b/axum/src/extract/matched_path.rs index 8965bd30bf..ac3c849214 100644 --- a/axum/src/extract/matched_path.rs +++ b/axum/src/extract/matched_path.rs @@ -64,13 +64,10 @@ impl MatchedPath { } #[async_trait] -impl FromRequest for MatchedPath -where - B: Send, -{ +impl FromRequest for MatchedPath { type Rejection = MatchedPathRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let matched_path = req .extensions() .get::() diff --git a/axum/src/extract/mod.rs b/axum/src/extract/mod.rs index 6f0435f6e9..ac920c9fcd 100644 --- a/axum/src/extract/mod.rs +++ b/axum/src/extract/mod.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../docs/extract.md")] +use axum_core::body::Body; use http::header; use rejection::*; @@ -21,12 +22,8 @@ pub use axum_core::extract::{FromRequest, RequestParts}; #[doc(inline)] #[allow(deprecated)] pub use self::{ - connect_info::ConnectInfo, - content_length_limit::ContentLengthLimit, - host::Host, - path::Path, - raw_query::RawQuery, - request_parts::{BodyStream, RawBody}, + connect_info::ConnectInfo, content_length_limit::ContentLengthLimit, host::Host, path::Path, + raw_query::RawQuery, request_parts::BodyStream, }; #[doc(no_inline)] @@ -73,15 +70,12 @@ pub use self::ws::WebSocketUpgrade; #[doc(no_inline)] pub use crate::TypedHeader; -pub(crate) fn take_body(req: &mut RequestParts) -> Result { +pub(crate) fn take_body(req: &mut RequestParts) -> Result { req.take_body().ok_or_else(BodyAlreadyExtracted::default) } // this is duplicated in `axum-extra/src/extract/form.rs` -pub(super) fn has_content_type( - req: &RequestParts, - expected_content_type: &mime::Mime, -) -> bool { +pub(super) fn has_content_type(req: &RequestParts, expected_content_type: &mime::Mime) -> bool { let content_type = if let Some(content_type) = req.headers().get(header::CONTENT_TYPE) { content_type } else { diff --git a/axum/src/extract/multipart.rs b/axum/src/extract/multipart.rs index 8f58455fb9..4b3ed93b14 100644 --- a/axum/src/extract/multipart.rs +++ b/axum/src/extract/multipart.rs @@ -3,8 +3,7 @@ //! See [`Multipart`] for more details. use super::{rejection::*, BodyStream, FromRequest, RequestParts}; -use crate::body::{Bytes, HttpBody}; -use crate::BoxError; +use crate::body::Bytes; use async_trait::async_trait; use futures_util::stream::Stream; use http::header::{HeaderMap, CONTENT_TYPE}; @@ -50,14 +49,10 @@ pub struct Multipart { } #[async_trait] -impl FromRequest for Multipart -where - B: HttpBody + Default + Unpin + Send + 'static, - B::Error: Into, -{ +impl FromRequest for Multipart { type Rejection = MultipartRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let stream = BodyStream::from_request(req).await?; let headers = req.headers(); let boundary = parse_boundary(headers).ok_or(InvalidBoundary)?; diff --git a/axum/src/extract/path/mod.rs b/axum/src/extract/path/mod.rs index f559ae1fb0..317eee59a1 100644 --- a/axum/src/extract/path/mod.rs +++ b/axum/src/extract/path/mod.rs @@ -163,14 +163,13 @@ impl DerefMut for Path { } #[async_trait] -impl FromRequest for Path +impl FromRequest for Path where T: DeserializeOwned + Send, - B: Send, { type Rejection = PathRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let params = match req.extensions_mut().get::() { Some(UrlParams::Params(params)) => params, Some(UrlParams::InvalidUtf8InPathParam { key }) => { @@ -411,9 +410,8 @@ impl std::error::Error for FailedToDeserializePathParams {} #[cfg(test)] mod tests { use super::*; - use crate::{routing::get, test_helpers::*, Router}; + use crate::{body::Body, routing::get, test_helpers::*, Router}; use http::{Request, StatusCode}; - use hyper::Body; use std::collections::HashMap; #[tokio::test] diff --git a/axum/src/extract/query.rs b/axum/src/extract/query.rs index c267ce05fc..b265f3d00f 100644 --- a/axum/src/extract/query.rs +++ b/axum/src/extract/query.rs @@ -49,14 +49,13 @@ use std::ops::Deref; pub struct Query(pub T); #[async_trait] -impl FromRequest for Query +impl FromRequest for Query where T: DeserializeOwned, - B: Send, { type Rejection = QueryRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let query = req.uri().query().unwrap_or_default(); let value = serde_urlencoded::from_str(query) .map_err(FailedToDeserializeQueryString::__private_new::)?; @@ -75,13 +74,19 @@ impl Deref for Query { #[cfg(test)] mod tests { use super::*; + use crate::body::Body; use crate::extract::RequestParts; use http::Request; use serde::Deserialize; use std::fmt::Debug; async fn check(uri: impl AsRef, value: T) { - let mut req = RequestParts::new(Request::builder().uri(uri.as_ref()).body(()).unwrap()); + let mut req = RequestParts::new( + Request::builder() + .uri(uri.as_ref()) + .body(Body::empty()) + .unwrap(), + ); assert_eq!(Query::::from_request(&mut req).await.unwrap().0, value); } diff --git a/axum/src/extract/raw_query.rs b/axum/src/extract/raw_query.rs index 463c31d88a..3334013fd4 100644 --- a/axum/src/extract/raw_query.rs +++ b/axum/src/extract/raw_query.rs @@ -27,13 +27,10 @@ use std::convert::Infallible; pub struct RawQuery(pub Option); #[async_trait] -impl FromRequest for RawQuery -where - B: Send, -{ +impl FromRequest for RawQuery { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let query = req.uri().query().map(|query| query.to_owned()); Ok(Self(query)) } diff --git a/axum/src/extract/request_parts.rs b/axum/src/extract/request_parts.rs index 02b044c50c..6c9e93f24e 100644 --- a/axum/src/extract/request_parts.rs +++ b/axum/src/extract/request_parts.rs @@ -1,7 +1,7 @@ use super::{rejection::*, take_body, Extension, FromRequest, RequestParts}; use crate::{ - body::{Body, Bytes, HttpBody}, - BoxError, Error, + body::{Bytes, HttpBody}, + Error, }; use async_trait::async_trait; use futures_util::stream::Stream; @@ -86,13 +86,10 @@ pub struct OriginalUri(pub Uri); #[cfg(feature = "original-uri")] #[async_trait] -impl FromRequest for OriginalUri -where - B: Send, -{ +impl FromRequest for OriginalUri { type Rejection = Infallible; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { let uri = Extension::::from_request(req) .await .unwrap_or_else(|_| Extension(OriginalUri(req.uri().clone()))) @@ -140,18 +137,11 @@ impl Stream for BodyStream { } #[async_trait] -impl FromRequest for BodyStream -where - B: HttpBody + Send + 'static, - B::Data: Into, - B::Error: Into, -{ +impl FromRequest for BodyStream { type Rejection = BodyAlreadyExtracted; - async fn from_request(req: &mut RequestParts) -> Result { - let body = take_body(req)? - .map_data(Into::into) - .map_err(|err| Error::new(err.into())); + async fn from_request(req: &mut RequestParts) -> Result { + let body = take_body(req)?.map_data(Into::into).map_err(Error::new); let stream = BodyStream(SyncWrapper::new(Box::pin(body))); Ok(stream) } @@ -169,45 +159,6 @@ fn body_stream_traits() { crate::test_helpers::assert_sync::(); } -/// Extractor that extracts the raw request body. -/// -/// # Example -/// -/// ```rust,no_run -/// use axum::{ -/// extract::RawBody, -/// routing::get, -/// Router, -/// }; -/// use futures::StreamExt; -/// -/// async fn handler(RawBody(body): RawBody) { -/// // ... -/// } -/// -/// let app = Router::new().route("/users", get(handler)); -/// # async { -/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); -/// # }; -/// ``` -/// -/// [`body::Body`]: crate::body::Body -#[derive(Debug, Default, Clone)] -pub struct RawBody(pub B); - -#[async_trait] -impl FromRequest for RawBody -where - B: Send, -{ - type Rejection = BodyAlreadyExtracted; - - async fn from_request(req: &mut RequestParts) -> Result { - let body = take_body(req)?; - Ok(Self(body)) - } -} - #[cfg(test)] mod tests { use crate::{ diff --git a/axum/src/extract/ws.rs b/axum/src/extract/ws.rs index 7ac75ab697..4b2473fc8b 100644 --- a/axum/src/extract/ws.rs +++ b/axum/src/extract/ws.rs @@ -244,13 +244,10 @@ impl WebSocketUpgrade { } #[async_trait] -impl FromRequest for WebSocketUpgrade -where - B: Send, -{ +impl FromRequest for WebSocketUpgrade { type Rejection = WebSocketUpgradeRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { if req.method() != Method::GET { return Err(MethodNotGet.into()); } @@ -288,7 +285,7 @@ where } } -fn header_eq(req: &RequestParts, key: HeaderName, value: &'static str) -> bool { +fn header_eq(req: &RequestParts, key: HeaderName, value: &'static str) -> bool { if let Some(header) = req.headers().get(&key) { header.as_bytes().eq_ignore_ascii_case(value.as_bytes()) } else { @@ -296,7 +293,7 @@ fn header_eq(req: &RequestParts, key: HeaderName, value: &'static str) -> } } -fn header_contains(req: &RequestParts, key: HeaderName, value: &'static str) -> bool { +fn header_contains(req: &RequestParts, key: HeaderName, value: &'static str) -> bool { let header = if let Some(header) = req.headers().get(&key) { header } else { diff --git a/axum/src/form.rs b/axum/src/form.rs index 9974a46036..83f11ff20a 100644 --- a/axum/src/form.rs +++ b/axum/src/form.rs @@ -1,6 +1,5 @@ -use crate::body::{Bytes, HttpBody}; +use crate::body::Bytes; use crate::extract::{has_content_type, rejection::*, FromRequest, RequestParts}; -use crate::BoxError; use async_trait::async_trait; use axum_core::response::{IntoResponse, Response}; use http::header::CONTENT_TYPE; @@ -56,16 +55,13 @@ use std::ops::Deref; pub struct Form(pub T); #[async_trait] -impl FromRequest for Form +impl FromRequest for Form where T: DeserializeOwned, - B: HttpBody + Send, - B::Data: Send, - B::Error: Into, { type Rejection = FormRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { if req.method() == Method::GET { let query = req.uri().query().unwrap_or_default(); let value = serde_urlencoded::from_str(query) @@ -112,7 +108,7 @@ impl Deref for Form { #[cfg(test)] mod tests { use super::*; - use crate::body::{Empty, Full}; + use crate::body::Body; use crate::extract::RequestParts; use http::Request; use serde::{Deserialize, Serialize}; @@ -128,7 +124,7 @@ mod tests { let mut req = RequestParts::new( Request::builder() .uri(uri.as_ref()) - .body(Empty::::new()) + .body(Body::empty()) .unwrap(), ); assert_eq!(Form::::from_request(&mut req).await.unwrap().0, value); @@ -143,9 +139,7 @@ mod tests { http::header::CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref(), ) - .body(Full::::new( - serde_urlencoded::to_string(&value).unwrap().into(), - )) + .body(Body::from(serde_urlencoded::to_string(&value).unwrap())) .unwrap(), ); assert_eq!(Form::::from_request(&mut req).await.unwrap().0, value); @@ -209,13 +203,12 @@ mod tests { .uri("http://example.com/test") .method(Method::POST) .header(http::header::CONTENT_TYPE, mime::APPLICATION_JSON.as_ref()) - .body(Full::::new( + .body(Body::from( serde_urlencoded::to_string(&Pagination { size: Some(10), page: None, }) - .unwrap() - .into(), + .unwrap(), )) .unwrap(), ); diff --git a/axum/src/handler/future.rs b/axum/src/handler/future.rs index b8b3e4e867..cb02508dbf 100644 --- a/axum/src/handler/future.rs +++ b/axum/src/handler/future.rs @@ -1,6 +1,6 @@ //! Handler future types. -use crate::response::Response; +use crate::{body::Body, response::Response}; use futures_util::future::Map; use http::Request; use pin_project_lite::pin_project; @@ -19,29 +19,29 @@ opaque_future! { pin_project! { /// The response future for [`Layered`](super::Layered). - pub struct LayeredFuture + pub struct LayeredFuture where - S: Service>, + S: Service>, { #[pin] - inner: Map>, fn(Result) -> Response>, + inner: Map>, fn(Result) -> Response>, } } -impl LayeredFuture +impl LayeredFuture where - S: Service>, + S: Service>, { pub(super) fn new( - inner: Map>, fn(Result) -> Response>, + inner: Map>, fn(Result) -> Response>, ) -> Self { Self { inner } } } -impl Future for LayeredFuture +impl Future for LayeredFuture where - S: Service>, + S: Service>, { type Output = Response; diff --git a/axum/src/handler/into_service.rs b/axum/src/handler/into_service.rs index 34f36b2d21..a0eb608283 100644 --- a/axum/src/handler/into_service.rs +++ b/axum/src/handler/into_service.rs @@ -1,5 +1,5 @@ use super::Handler; -use crate::response::Response; +use crate::{body::Body, response::Response}; use http::Request; use std::{ convert::Infallible, @@ -12,19 +12,19 @@ use tower_service::Service; /// An adapter that makes a [`Handler`] into a [`Service`]. /// /// Created with [`Handler::into_service`]. -pub struct IntoService { +pub struct IntoService { handler: H, - _marker: PhantomData (T, B)>, + _marker: PhantomData T>, } #[test] fn traits() { use crate::test_helpers::*; - assert_send::>(); - assert_sync::>(); + assert_send::>(); + assert_sync::>(); } -impl IntoService { +impl IntoService { pub(super) fn new(handler: H) -> Self { Self { handler, @@ -33,7 +33,7 @@ impl IntoService { } } -impl fmt::Debug for IntoService { +impl fmt::Debug for IntoService { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoService") .field(&format_args!("...")) @@ -41,7 +41,7 @@ impl fmt::Debug for IntoService { } } -impl Clone for IntoService +impl Clone for IntoService where H: Clone, { @@ -53,10 +53,9 @@ where } } -impl Service> for IntoService +impl Service> for IntoService where - H: Handler + Clone + Send + 'static, - B: Send + 'static, + H: Handler + Clone + Send + 'static, { type Response = Response; type Error = Infallible; @@ -70,7 +69,7 @@ where Poll::Ready(Ok(())) } - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { use futures_util::future::FutureExt; let handler = self.handler.clone(); diff --git a/axum/src/handler/mod.rs b/axum/src/handler/mod.rs index 69482fecef..1d016e42f0 100644 --- a/axum/src/handler/mod.rs +++ b/axum/src/handler/mod.rs @@ -61,12 +61,12 @@ pub use self::into_service::IntoService; /// See the [module docs](crate::handler) for more details. /// #[doc = include_str!("../docs/debugging_handler_type_errors.md")] -pub trait Handler: Clone + Send + Sized + 'static { +pub trait Handler: Clone + Send + Sized + 'static { /// The type of future calling this handler returns. type Future: Future + Send + 'static; /// Call the handler with the given request. - fn call(self, req: Request) -> Self::Future; + fn call(self, req: Request) -> Self::Future; /// Apply a [`tower::Layer`] to the handler. /// @@ -106,7 +106,7 @@ pub trait Handler: Clone + Send + Sized + 'static { /// ``` fn layer(self, layer: L) -> Layered where - L: Layer>, + L: Layer>, { Layered::new(layer.layer(self.into_service())) } @@ -143,7 +143,7 @@ pub trait Handler: Clone + Send + Sized + 'static { /// ``` /// /// [`Router::fallback`]: crate::routing::Router::fallback - fn into_service(self) -> IntoService { + fn into_service(self) -> IntoService { IntoService::new(self) } @@ -170,7 +170,7 @@ pub trait Handler: Clone + Send + Sized + 'static { /// ``` /// /// [`MakeService`]: tower::make::MakeService - fn into_make_service(self) -> IntoMakeService> { + fn into_make_service(self) -> IntoMakeService> { IntoMakeService::new(self.into_service()) } @@ -204,21 +204,20 @@ pub trait Handler: Clone + Send + Sized + 'static { /// [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info fn into_make_service_with_connect_info( self, - ) -> IntoMakeServiceWithConnectInfo, C> { + ) -> IntoMakeServiceWithConnectInfo, C> { IntoMakeServiceWithConnectInfo::new(self.into_service()) } } -impl Handler<(), B> for F +impl Handler<()> for F where F: FnOnce() -> Fut + Clone + Send + 'static, Fut: Future + Send, Res: IntoResponse, - B: Send + 'static, { type Future = Pin + Send>>; - fn call(self, _req: Request) -> Self::Future { + fn call(self, _req: Request) -> Self::Future { Box::pin(async move { self().await.into_response() }) } } @@ -226,17 +225,16 @@ where macro_rules! impl_handler { ( $($ty:ident),* $(,)? ) => { #[allow(non_snake_case)] - impl Handler<($($ty,)*), B> for F + impl Handler<($($ty,)*)> for F where F: FnOnce($($ty,)*) -> Fut + Clone + Send + 'static, Fut: Future + Send, - B: Send + 'static, Res: IntoResponse, - $( $ty: FromRequest + Send,)* + $( $ty: FromRequest + Send,)* { type Future = Pin + Send>>; - fn call(self, req: Request) -> Self::Future { + fn call(self, req: Request) -> Self::Future { Box::pin(async move { let mut req = RequestParts::new(req); @@ -284,19 +282,18 @@ where } } -impl Handler for Layered +impl Handler for Layered where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Error: IntoResponse, S::Future: Send, T: 'static, - ReqBody: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { - type Future = future::LayeredFuture; + type Future = future::LayeredFuture; - fn call(self, req: Request) -> Self::Future { + fn call(self, req: Request) -> Self::Future { use futures_util::future::{FutureExt, Map}; let future: Map<_, fn(Result) -> _> = diff --git a/axum/src/json.rs b/axum/src/json.rs index e1d068fa1b..2f5190e9ff 100644 --- a/axum/src/json.rs +++ b/axum/src/json.rs @@ -1,7 +1,6 @@ use crate::{ - body::{Bytes, HttpBody}, + body::Bytes, extract::{rejection::*, FromRequest, RequestParts}, - BoxError, }; use async_trait::async_trait; use axum_core::response::{IntoResponse, Response}; @@ -93,16 +92,13 @@ use std::ops::{Deref, DerefMut}; pub struct Json(pub T); #[async_trait] -impl FromRequest for Json +impl FromRequest for Json where T: DeserializeOwned, - B: HttpBody + Send, - B::Data: Send, - B::Error: Into, { type Rejection = JsonRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { if json_content_type(req) { let bytes = Bytes::from_request(req).await?; @@ -135,7 +131,7 @@ where } } -fn json_content_type(req: &RequestParts) -> bool { +fn json_content_type(req: &RequestParts) -> bool { let content_type = if let Some(content_type) = req.headers().get(header::CONTENT_TYPE) { content_type } else { diff --git a/axum/src/middleware/from_extractor.rs b/axum/src/middleware/from_extractor.rs index 45bb951380..905e6c0800 100644 --- a/axum/src/middleware/from_extractor.rs +++ b/axum/src/middleware/from_extractor.rs @@ -4,6 +4,7 @@ use crate::{ response::{IntoResponse, Response}, BoxError, }; +use axum_core::body::Body; use futures_util::{future::BoxFuture, ready}; use http::Request; use pin_project_lite::pin_project; @@ -166,24 +167,23 @@ where } } -impl Service> for FromExtractor +impl Service> for FromExtractor where - E: FromRequest + 'static, - ReqBody: Default + Send + 'static, - S: Service, Response = Response> + Clone, + E: FromRequest + 'static, + S: Service, Response = Response> + Clone, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { type Response = Response; type Error = S::Error; - type Future = ResponseFuture; + type Future = ResponseFuture; #[inline] fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { self.inner.poll_ready(cx) } - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { let extract_future = Box::pin(async move { let mut req = RequestParts::new(req); let extracted = E::from_request(&mut req).await; @@ -202,34 +202,33 @@ where pin_project! { /// Response future for [`FromExtractor`]. #[allow(missing_debug_implementations)] - pub struct ResponseFuture + pub struct ResponseFuture where - E: FromRequest, - S: Service>, + E: FromRequest, + S: Service>, { #[pin] - state: State, + state: State, svc: Option, } } pin_project! { #[project = StateProj] - enum State + enum State where - E: FromRequest, - S: Service>, + E: FromRequest, + S: Service>, { - Extracting { future: BoxFuture<'static, (RequestParts, Result)> }, + Extracting { future: BoxFuture<'static, (RequestParts, Result)> }, Call { #[pin] future: S::Future }, } } -impl Future for ResponseFuture +impl Future for ResponseFuture where - E: FromRequest, - S: Service, Response = Response>, - ReqBody: Default, + E: FromRequest, + S: Service, Response = Response>, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { @@ -279,13 +278,10 @@ mod tests { struct RequireAuth; #[async_trait::async_trait] - impl FromRequest for RequireAuth - where - B: Send, - { + impl FromRequest for RequireAuth { type Rejection = StatusCode; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { if let Some(auth) = req .headers() .get(header::AUTHORIZATION) diff --git a/axum/src/middleware/from_fn.rs b/axum/src/middleware/from_fn.rs index 8e46fa690f..fadbf070ff 100644 --- a/axum/src/middleware/from_fn.rs +++ b/axum/src/middleware/from_fn.rs @@ -1,5 +1,5 @@ use crate::{ - body::{self, Bytes, HttpBody}, + body::{self, Body, Bytes, HttpBody}, response::{IntoResponse, Response}, BoxError, }; @@ -256,18 +256,17 @@ where macro_rules! impl_service { ( $($ty:ident),* $(,)? ) => { #[allow(non_snake_case)] - impl Service> for FromFn + impl Service> for FromFn where - F: FnMut($($ty),*, Next) -> Fut + Clone + Send + 'static, - $( $ty: FromRequest + Send, )* + F: FnMut($($ty),*, Next) -> Fut + Clone + Send + 'static, + $( $ty: FromRequest + Send, )* Fut: Future + Send + 'static, Out: IntoResponse + 'static, - S: Service, Response = Response, Error = Infallible> + S: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, S::Future: Send + 'static, - ReqBody: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, { @@ -279,7 +278,7 @@ macro_rules! impl_service { self.inner.poll_ready(cx) } - fn call(&mut self, req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { let not_ready_inner = self.inner.clone(); let ready_inner = std::mem::replace(&mut self.inner, not_ready_inner); @@ -326,13 +325,14 @@ where } /// The remainder of a middleware stack, including the handler. -pub struct Next { - inner: BoxCloneService, Response, Infallible>, +#[derive(Debug)] +pub struct Next { + inner: BoxCloneService, Response, Infallible>, } -impl Next { +impl Next { /// Execute the remaining middleware stack. - pub async fn run(mut self, req: Request) -> Response { + pub async fn run(mut self, req: Request) -> Response { match self.inner.call(req).await { Ok(res) => res, Err(err) => match err {}, @@ -340,14 +340,6 @@ impl Next { } } -impl fmt::Debug for Next { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("FromFnLayer") - .field("inner", &self.inner) - .finish() - } -} - /// Response future for [`FromFn`]. pub struct ResponseFuture { inner: BoxFuture<'static, Response>, @@ -370,13 +362,13 @@ impl fmt::Debug for ResponseFuture { #[cfg(test)] mod tests { use super::*; - use crate::{body::Empty, routing::get, Router}; + use crate::{routing::get, Router}; use http::{HeaderMap, StatusCode}; use tower::ServiceExt; #[tokio::test] async fn basic() { - async fn insert_header(mut req: Request, next: Next) -> impl IntoResponse { + async fn insert_header(mut req: Request, next: Next) -> impl IntoResponse { req.headers_mut() .insert("x-axum-test", "ok".parse().unwrap()); @@ -392,12 +384,7 @@ mod tests { .layer(from_fn(insert_header)); let res = app - .oneshot( - Request::builder() - .uri("/") - .body(body::boxed(Empty::new())) - .unwrap(), - ) + .oneshot(Request::builder().uri("/").body(Body::empty()).unwrap()) .await .unwrap(); assert_eq!(res.status(), StatusCode::OK); diff --git a/axum/src/response/mod.rs b/axum/src/response/mod.rs index 695b931c22..3c139a675d 100644 --- a/axum/src/response/mod.rs +++ b/axum/src/response/mod.rs @@ -61,7 +61,7 @@ impl From for Html { #[cfg(test)] mod tests { use crate::extract::Extension; - use crate::{body::Body, routing::get, Router}; + use crate::{routing::get, Router}; use axum_core::response::IntoResponse; use http::HeaderMap; use http::{StatusCode, Uri}; @@ -93,7 +93,7 @@ mod tests { } } - Router::::new() + Router::new() .route("/", get(impl_trait_ok)) .route("/", get(impl_trait_err)) .route("/", get(impl_trait_both)) @@ -203,7 +203,7 @@ mod tests { ) } - Router::::new() + Router::new() .route("/", get(status)) .route("/", get(status_headermap)) .route("/", get(status_header_array)) diff --git a/axum/src/routing/method_routing.rs b/axum/src/routing/method_routing.rs index 4edb8bdb66..ade00671e9 100644 --- a/axum/src/routing/method_routing.rs +++ b/axum/src/routing/method_routing.rs @@ -76,9 +76,9 @@ macro_rules! top_level_service_fn { $name:ident, $method:ident ) => { $(#[$m])+ - pub fn $name(svc: S) -> MethodRouter + pub fn $name(svc: S) -> MethodRouter where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, @@ -137,10 +137,9 @@ macro_rules! top_level_handler_fn { $name:ident, $method:ident ) => { $(#[$m])+ - pub fn $name(handler: H) -> MethodRouter + pub fn $name(handler: H) -> MethodRouter where - H: Handler, - B: Send + 'static, + H: Handler, T: 'static, { on(MethodFilter::$method, handler) @@ -210,7 +209,7 @@ macro_rules! chained_service_fn { $(#[$m])+ pub fn $name(self, svc: S) -> Self where - S: Service, Response = Response, Error = E> + S: Service, Response = Response, Error = E> + Clone + Send + 'static, @@ -274,7 +273,7 @@ macro_rules! chained_handler_fn { $(#[$m])+ pub fn $name(self, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { self.on(MethodFilter::$method, handler) @@ -316,12 +315,9 @@ top_level_service_fn!(trace_service, TRACE); /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` -pub fn on_service( - filter: MethodFilter, - svc: S, -) -> MethodRouter +pub fn on_service(filter: MethodFilter, svc: S) -> MethodRouter where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, @@ -382,9 +378,9 @@ where /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` -pub fn any_service(svc: S) -> MethodRouter +pub fn any_service(svc: S) -> MethodRouter where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, S::Future: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, @@ -420,10 +416,9 @@ top_level_handler_fn!(trace, TRACE); /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` -pub fn on(filter: MethodFilter, handler: H) -> MethodRouter +pub fn on(filter: MethodFilter, handler: H) -> MethodRouter where - H: Handler, - B: Send + 'static, + H: Handler, T: 'static, { MethodRouter::new().on(filter, handler) @@ -466,10 +461,9 @@ where /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` -pub fn any(handler: H) -> MethodRouter +pub fn any(handler: H) -> MethodRouter where - H: Handler, - B: Send + 'static, + H: Handler, T: 'static, { MethodRouter::new() @@ -479,18 +473,18 @@ where /// A [`Service`] that accepts requests based on a [`MethodFilter`] and /// allows chaining additional handlers and services. -pub struct MethodRouter { - get: Option>, - head: Option>, - delete: Option>, - options: Option>, - patch: Option>, - post: Option>, - put: Option>, - trace: Option>, - fallback: Fallback, +pub struct MethodRouter { + get: Option>, + head: Option>, + delete: Option>, + options: Option>, + patch: Option>, + post: Option>, + put: Option>, + trace: Option>, + fallback: Fallback, allow_header: AllowHeader, - _request_body: PhantomData (B, E)>, + _request_body: PhantomData E>, } #[derive(Clone)] @@ -503,7 +497,7 @@ enum AllowHeader { Bytes(BytesMut), } -impl fmt::Debug for MethodRouter { +impl fmt::Debug for MethodRouter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("MethodRouter") .field("get", &self.get) @@ -519,11 +513,11 @@ impl fmt::Debug for MethodRouter { } } -impl MethodRouter { +impl MethodRouter { /// Create a default `MethodRouter` that will respond with `405 Method Not Allowed` to all /// requests. pub fn new() -> Self { - let fallback = Route::new(service_fn(|_: Request| async { + let fallback = Route::new(service_fn(|_: Request| async { let mut response = Response::new(boxed(Empty::new())); *response.status_mut() = StatusCode::METHOD_NOT_ALLOWED; Ok(response) @@ -545,10 +539,7 @@ impl MethodRouter { } } -impl MethodRouter -where - B: Send + 'static, -{ +impl MethodRouter { /// Chain an additional handler that will accept requests matching the given /// `MethodFilter`. /// @@ -574,7 +565,7 @@ where /// ``` pub fn on(self, filter: MethodFilter, handler: H) -> Self where - H: Handler, + H: Handler, T: 'static, { self.on_service_boxed_response_body(filter, handler.into_service()) @@ -658,7 +649,7 @@ where } } -impl MethodRouter { +impl MethodRouter { /// Chain an additional service that will accept requests matching the given /// `MethodFilter`. /// @@ -686,10 +677,7 @@ impl MethodRouter { /// ``` pub fn on_service(self, filter: MethodFilter, svc: S) -> Self where - S: Service, Response = Response, Error = E> - + Clone - + Send - + 'static, + S: Service, Response = Response, Error = E> + Clone + Send + 'static, S::Future: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, @@ -709,10 +697,7 @@ impl MethodRouter { #[doc = include_str!("../docs/method_routing/fallback.md")] pub fn fallback(mut self, svc: S) -> Self where - S: Service, Response = Response, Error = E> - + Clone - + Send - + 'static, + S: Service, Response = Response, Error = E> + Clone + Send + 'static, S::Future: Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Error: Into, @@ -723,7 +708,7 @@ impl MethodRouter { fn fallback_boxed_response_body(mut self, svc: S) -> Self where - S: Service, Response = Response, Error = E> + Clone + Send + 'static, + S: Service, Response = Response, Error = E> + Clone + Send + 'static, S::Future: Send + 'static, { self.fallback = Fallback::Custom(Route::new(svc)); @@ -731,17 +716,14 @@ impl MethodRouter { } #[doc = include_str!("../docs/method_routing/layer.md")] - pub fn layer( - self, - layer: L, - ) -> MethodRouter + pub fn layer(self, layer: L) -> MethodRouter where - L: Layer>, - L::Service: Service, Response = Response, Error = NewError> + L: Layer>, + L::Service: Service, Response = Response, Error = NewError> + Clone + Send + 'static, - >>::Future: Send + 'static, + >>::Future: Send + 'static, NewResBody: HttpBody + Send + 'static, NewResBody::Error: Into, { @@ -768,14 +750,14 @@ impl MethodRouter { } #[doc = include_str!("../docs/method_routing/route_layer.md")] - pub fn route_layer(self, layer: L) -> MethodRouter + pub fn route_layer(self, layer: L) -> MethodRouter where - L: Layer>, - L::Service: Service, Response = Response, Error = E> + L: Layer>, + L::Service: Service, Response = Response, Error = E> + Clone + Send + 'static, - >>::Future: Send + 'static, + >>::Future: Send + 'static, NewResBody: HttpBody + Send + 'static, NewResBody::Error: Into, { @@ -802,7 +784,7 @@ impl MethodRouter { } #[doc = include_str!("../docs/method_routing/merge.md")] - pub fn merge(self, other: MethodRouter) -> Self { + pub fn merge(self, other: MethodRouter) -> Self { macro_rules! merge { ( $first:ident, $second:ident ) => { match ($first, $second) { @@ -894,22 +876,21 @@ impl MethodRouter { /// Apply a [`HandleErrorLayer`]. /// /// This is a convenience method for doing `self.layer(HandleErrorLayer::new(f))`. - pub fn handle_error(self, f: F) -> MethodRouter + pub fn handle_error(self, f: F) -> MethodRouter where F: Clone + Send + 'static, - HandleError, F, T>: - Service, Response = Response, Error = Infallible>, - , F, T> as Service>>::Future: Send, + HandleError, F, T>: + Service, Response = Response, Error = Infallible>, + , F, T> as Service>>::Future: Send, T: 'static, E: 'static, - ReqBody: 'static, { self.layer(HandleErrorLayer::new(f)) } fn on_service_boxed_response_body(self, filter: MethodFilter, svc: S) -> Self where - S: Service, Response = Response, Error = E> + Clone + Send + 'static, + S: Service, Response = Response, Error = E> + Clone + Send + 'static, S::Future: Send + 'static, { macro_rules! set_service { @@ -1009,7 +990,7 @@ fn append_allow_header(allow_header: &mut AllowHeader, method: &'static str) { } } -impl Clone for MethodRouter { +impl Clone for MethodRouter { fn clone(&self) -> Self { Self { get: self.get.clone(), @@ -1027,22 +1008,20 @@ impl Clone for MethodRouter { } } -impl Default for MethodRouter -where - B: Send + 'static, -{ +impl Default for MethodRouter { fn default() -> Self { Self::new() } } -impl Service> for MethodRouter +impl Service> for MethodRouter where - B: HttpBody, + B: HttpBody + Send + 'static, + B::Error: Into, { type Response = Response; type Error = E; - type Future = RouteFuture; + type Future = RouteFuture; #[inline] fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { @@ -1066,6 +1045,8 @@ where }; } + let req = req.map(Body::wrap_body); + let method = req.method().clone(); // written with a pattern match like this to ensure we call all routes diff --git a/axum/src/routing/mod.rs b/axum/src/routing/mod.rs index 4cf7abbeb0..d50ec4c3ca 100644 --- a/axum/src/routing/mod.rs +++ b/axum/src/routing/mod.rs @@ -62,51 +62,24 @@ impl RouteId { } /// The router type for composing handlers and services. -pub struct Router { - routes: HashMap>, +#[derive(Clone, Debug)] +pub struct Router { + routes: HashMap, node: Arc, - fallback: Fallback, + fallback: Fallback, nested_at_root: bool, } -impl Clone for Router { - fn clone(&self) -> Self { - Self { - routes: self.routes.clone(), - node: Arc::clone(&self.node), - fallback: self.fallback.clone(), - nested_at_root: self.nested_at_root, - } - } -} - -impl Default for Router -where - B: HttpBody + Send + 'static, -{ +impl Default for Router { fn default() -> Self { Self::new() } } -impl fmt::Debug for Router { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Router") - .field("routes", &self.routes) - .field("node", &self.node) - .field("fallback", &self.fallback) - .field("nested_at_root", &self.nested_at_root) - .finish() - } -} - pub(crate) const NEST_TAIL_PARAM: &str = "__private__axum_nest_tail_param"; const NEST_TAIL_PARAM_CAPTURE: &str = "/*__private__axum_nest_tail_param"; -impl Router -where - B: HttpBody + Send + 'static, -{ +impl Router { /// Create a new `Router`. /// /// Unless you add additional routes this will respond with `404 Not Found` to @@ -123,7 +96,7 @@ where #[doc = include_str!("../docs/routing/route.md")] pub fn route(mut self, path: &str, service: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, { if path.is_empty() { @@ -132,7 +105,7 @@ where panic!("Paths must start with a `/`"); } - let service = match try_downcast::, _>(service) { + let service = match try_downcast::(service) { Ok(_) => { panic!("Invalid route: `Router::route` cannot be used with `Router`s. Use `Router::nest` instead") } @@ -141,7 +114,7 @@ where let id = RouteId::next(); - let service = match try_downcast::, _>(service) { + let service = match try_downcast::, _>(service) { Ok(method_router) => { if let Some((route_id, Endpoint::MethodRouter(prev_method_router))) = self .node @@ -177,7 +150,7 @@ where #[doc = include_str!("../docs/routing/nest.md")] pub fn nest(mut self, mut path: &str, svc: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, { if path.is_empty() { @@ -195,7 +168,7 @@ where self.nested_at_root = true; } - match try_downcast::, _>(svc) { + match try_downcast::(svc) { // if the user is nesting a `Router` we can implement nesting // by simplying copying all the routes and adding the prefix in // front @@ -256,7 +229,7 @@ where #[doc = include_str!("../docs/routing/merge.md")] pub fn merge(mut self, other: R) -> Self where - R: Into>, + R: Into, { let Router { routes, @@ -291,13 +264,13 @@ where } #[doc = include_str!("../docs/routing/layer.md")] - pub fn layer(self, layer: L) -> Router + pub fn layer(self, layer: L) -> Router where - L: Layer>, + L: Layer, L::Service: - Service, Response = Response> + Clone + Send + 'static, - >>::Error: Into + 'static, - >>::Future: Send + 'static, + Service, Response = Response> + Clone + Send + 'static, + >>::Error: Into + 'static, + >>::Future: Send + 'static, NewResBody: HttpBody + Send + 'static, NewResBody::Error: Into, { @@ -334,10 +307,11 @@ where #[doc = include_str!("../docs/routing/route_layer.md")] pub fn route_layer(self, layer: L) -> Self where - L: Layer>, - L::Service: Service, Response = Response> + Clone + Send + 'static, - >>::Error: Into + 'static, - >>::Future: Send + 'static, + L: Layer, + L::Service: + Service, Response = Response> + Clone + Send + 'static, + >>::Error: Into + 'static, + >>::Future: Send + 'static, NewResBody: HttpBody + Send + 'static, NewResBody::Error: Into, { @@ -372,7 +346,7 @@ where #[doc = include_str!("../docs/routing/fallback.md")] pub fn fallback(mut self, svc: T) -> Self where - T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, + T: Service, Response = Response, Error = Infallible> + Clone + Send + 'static, T::Future: Send + 'static, { self.fallback = Fallback::Custom(Route::new(svc)); @@ -415,8 +389,8 @@ where fn call_route( &self, match_: matchit::Match<&RouteId>, - mut req: Request, - ) -> RouteFuture { + mut req: Request, + ) -> RouteFuture { let id = *match_.value; #[cfg(feature = "matched-path")] @@ -470,13 +444,14 @@ where } } -impl Service> for Router +impl Service> for Router where - B: HttpBody + Send + 'static, + B: HttpBody + Send + 'static, + B::Error: Into, { type Response = Response; type Error = Infallible; - type Future = RouteFuture; + type Future = RouteFuture; #[inline] fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { @@ -484,7 +459,9 @@ where } #[inline] - fn call(&mut self, mut req: Request) -> Self::Future { + fn call(&mut self, req: Request) -> Self::Future { + let mut req = req.map(Body::wrap_body); + #[cfg(feature = "original-uri")] { use crate::extract::OriginalUri; @@ -552,12 +529,12 @@ impl fmt::Debug for Node { } } -enum Fallback { - Default(Route), - Custom(Route), +enum Fallback { + Default(Route), + Custom(Route), } -impl Clone for Fallback { +impl Clone for Fallback { fn clone(&self) -> Self { match self { Fallback::Default(inner) => Fallback::Default(inner.clone()), @@ -566,7 +543,7 @@ impl Clone for Fallback { } } -impl fmt::Debug for Fallback { +impl fmt::Debug for Fallback { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Default(inner) => f.debug_tuple("Default").field(inner).finish(), @@ -575,10 +552,10 @@ impl fmt::Debug for Fallback { } } -impl Fallback { - fn map(self, f: F) -> Fallback +impl Fallback { + fn map(self, f: F) -> Fallback where - F: FnOnce(Route) -> Route, + F: FnOnce(Route) -> Route, { match self { Fallback::Default(inner) => Fallback::Default(f(inner)), @@ -587,32 +564,15 @@ impl Fallback { } } -enum Endpoint { - MethodRouter(MethodRouter), - Route(Route), -} - -impl Clone for Endpoint { - fn clone(&self) -> Self { - match self { - Endpoint::MethodRouter(inner) => Endpoint::MethodRouter(inner.clone()), - Endpoint::Route(inner) => Endpoint::Route(inner.clone()), - } - } -} - -impl fmt::Debug for Endpoint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::MethodRouter(inner) => inner.fmt(f), - Self::Route(inner) => inner.fmt(f), - } - } +#[derive(Clone, Debug)] +enum Endpoint { + MethodRouter(MethodRouter), + Route(Route), } #[test] #[allow(warnings)] fn traits() { use crate::test_helpers::*; - assert_send::>(); + assert_send::(); } diff --git a/axum/src/routing/route.rs b/axum/src/routing/route.rs index 6e56d77a72..50ec037288 100644 --- a/axum/src/routing/route.rs +++ b/axum/src/routing/route.rs @@ -2,6 +2,7 @@ use crate::{ body::{boxed, Body, Empty, HttpBody}, response::Response, }; +use axum_core::BoxError; use bytes::Bytes; use http::{ header::{self, CONTENT_LENGTH}, @@ -25,12 +26,12 @@ use tower_service::Service; /// /// You normally shouldn't need to care about this type. It's used in /// [`Router::layer`](super::Router::layer). -pub struct Route(BoxCloneService, Response, E>); +pub struct Route(BoxCloneService, Response, E>); -impl Route { +impl Route { pub(super) fn new(svc: T) -> Self where - T: Service, Response = Response, Error = E> + Clone + Send + 'static, + T: Service, Response = Response, Error = E> + Clone + Send + 'static, T::Future: Send + 'static, { Self(BoxCloneService::new(svc)) @@ -38,31 +39,32 @@ impl Route { pub(crate) fn oneshot_inner( &mut self, - req: Request, - ) -> Oneshot, Response, E>, Request> { + req: Request, + ) -> Oneshot, Response, E>, Request> { self.0.clone().oneshot(req) } } -impl Clone for Route { +impl Clone for Route { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl fmt::Debug for Route { +impl fmt::Debug for Route { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Route").finish() } } -impl Service> for Route +impl Service> for Route where - B: HttpBody, + B: HttpBody + Send + 'static, + B::Error: Into, { type Response = Response; type Error = E; - type Future = RouteFuture; + type Future = RouteFuture; #[inline] fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { @@ -71,15 +73,16 @@ where #[inline] fn call(&mut self, req: Request) -> Self::Future { + let req = req.map(Body::wrap_body); RouteFuture::from_future(self.oneshot_inner(req)) } } pin_project! { /// Response future for [`Route`]. - pub struct RouteFuture { + pub struct RouteFuture { #[pin] - kind: RouteFutureKind, + kind: RouteFutureKind, strip_body: bool, allow_header: Option, } @@ -87,12 +90,12 @@ pin_project! { pin_project! { #[project = RouteFutureKindProj] - enum RouteFutureKind { + enum RouteFutureKind { Future { #[pin] future: Oneshot< - BoxCloneService, Response, E>, - Request, + BoxCloneService, Response, E>, + Request, >, }, Response { @@ -101,9 +104,9 @@ pin_project! { } } -impl RouteFuture { +impl RouteFuture { pub(crate) fn from_future( - future: Oneshot, Response, E>, Request>, + future: Oneshot, Response, E>, Request>, ) -> Self { Self { kind: RouteFutureKind::Future { future }, @@ -123,10 +126,7 @@ impl RouteFuture { } } -impl Future for RouteFuture -where - B: HttpBody, -{ +impl Future for RouteFuture { type Output = Result; #[inline] diff --git a/axum/src/routing/tests/merge.rs b/axum/src/routing/tests/merge.rs index 58af01511b..31a7bc9ae1 100644 --- a/axum/src/routing/tests/merge.rs +++ b/axum/src/routing/tests/merge.rs @@ -64,7 +64,7 @@ async fn multiple_ors_balanced_differently() { async fn test(name: &str, app: S) where - S: Service, Response = Response> + Clone + Send + 'static, + S: Service, Response = Response> + Clone + Send + 'static, ResBody: HttpBody + Send + 'static, ResBody::Data: Send, ResBody::Error: Into, diff --git a/axum/src/routing/tests/mod.rs b/axum/src/routing/tests/mod.rs index 5976f8a0fc..fe27634a91 100644 --- a/axum/src/routing/tests/mod.rs +++ b/axum/src/routing/tests/mod.rs @@ -1,5 +1,5 @@ use crate::{ - body::{Bytes, Empty}, + body::{Body, Bytes, Empty}, error_handling::HandleErrorLayer, extract::{self, Path}, handler::Handler, @@ -9,7 +9,6 @@ use crate::{ BoxError, Json, Router, }; use http::{header::CONTENT_LENGTH, HeaderMap, Method, Request, Response, StatusCode, Uri}; -use hyper::Body; use serde::Deserialize; use serde_json::{json, Value}; use std::{ @@ -720,3 +719,14 @@ async fn limited_body_with_streaming_body() { .await; assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); } + +#[allow(dead_code)] +fn adding_middleware_dont_change_request_body_type() -> Router { + Router::new() + .route("/", get(|_: Body| async {})) + .route("/", get(|_: String| async {})) + .route("/", get(|_: Bytes| async {})) + .route("/", get(|_: Json| async {})) + .route("/", get(|_: Request| async {})) + .layer(tower_http::limit::RequestBodyLimitLayer::new(1024)) +} diff --git a/axum/src/routing/tests/nest.rs b/axum/src/routing/tests/nest.rs index d4cb466c56..42367be520 100644 --- a/axum/src/routing/tests/nest.rs +++ b/axum/src/routing/tests/nest.rs @@ -294,7 +294,7 @@ async fn multiple_top_level_nests() { #[tokio::test] #[should_panic(expected = "Invalid route: nested routes cannot contain wildcards (*)")] async fn nest_cannot_contain_wildcards() { - Router::::new().nest("/one/*rest", Router::new()); + Router::new().nest("/one/*rest", Router::new()); } #[tokio::test] diff --git a/axum/src/typed_header.rs b/axum/src/typed_header.rs index 1ce72d04f8..0f2f7ea302 100644 --- a/axum/src/typed_header.rs +++ b/axum/src/typed_header.rs @@ -52,14 +52,13 @@ use std::{convert::Infallible, ops::Deref}; pub struct TypedHeader(pub T); #[async_trait] -impl FromRequest for TypedHeader +impl FromRequest for TypedHeader where T: headers::Header, - B: Send, { type Rejection = TypedHeaderRejection; - async fn from_request(req: &mut RequestParts) -> Result { + async fn from_request(req: &mut RequestParts) -> Result { match req.headers().typed_try_get::() { Ok(Some(value)) => Ok(Self(value)), Ok(None) => Err(TypedHeaderRejection {