Remove B type param: Follow ups (#1789)

Co-authored-by: Jonas Platte <[email protected]>
Co-authored-by: Michael Scofield <[email protected]>
This commit is contained in:
David Pedersen
2023-03-23 20:24:58 +01:00
co-authored by Jonas Platte Michael Scofield
parent 0d50d17304
commit 2ae0cdf7cf
70 changed files with 428 additions and 527 deletions
+2 -14
View File
@@ -1,6 +1,5 @@
//! HTTP body utilities. //! HTTP body utilities.
use crate::response::{IntoResponse, Response};
use crate::{BoxError, Error}; use crate::{BoxError, Error};
use bytes::Bytes; use bytes::Bytes;
use bytes::{Buf, BufMut}; use bytes::{Buf, BufMut};
@@ -13,14 +12,9 @@ use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use sync_wrapper::SyncWrapper; use sync_wrapper::SyncWrapper;
/// A boxed [`Body`] trait object. type BoxBody = http_body::combinators::UnsyncBoxBody<Bytes, Error>;
///
/// This is used in axum as the response body type for applications. It's
/// necessary to unify multiple response bodies types into one.
pub type BoxBody = http_body::combinators::UnsyncBoxBody<Bytes, Error>;
/// Convert a [`http_body::Body`] into a [`BoxBody`]. fn boxed<B>(body: B) -> BoxBody
pub fn boxed<B>(body: B) -> BoxBody
where where
B: http_body::Body<Data = Bytes> + Send + 'static, B: http_body::Body<Data = Bytes> + Send + 'static,
B::Error: Into<BoxError>, B::Error: Into<BoxError>,
@@ -230,12 +224,6 @@ where
} }
} }
impl IntoResponse for Body {
fn into_response(self) -> Response {
Response::new(self.0)
}
}
#[test] #[test]
fn test_try_downcast() { fn test_try_downcast() {
assert_eq!(try_downcast::<i32, _>(5_u32), Err(5_u32)); assert_eq!(try_downcast::<i32, _>(5_u32), Err(5_u32));
+16 -19
View File
@@ -1,7 +1,6 @@
use crate::body::Body; use crate::body::Body;
use crate::extract::{DefaultBodyLimitKind, FromRequest, FromRequestParts}; use crate::extract::{DefaultBodyLimitKind, FromRequest, FromRequestParts, Request};
use futures_util::future::BoxFuture; use futures_util::future::BoxFuture;
use http::Request;
use http_body::Limited; use http_body::Limited;
mod sealed { mod sealed {
@@ -23,9 +22,9 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// ``` /// ```
/// use axum::{ /// use axum::{
/// async_trait, /// async_trait,
/// extract::FromRequest, /// extract::{Request, FromRequest},
/// body::Body, /// body::Body,
/// http::{header::CONTENT_TYPE, Request, StatusCode}, /// http::{header::CONTENT_TYPE, StatusCode},
/// response::{IntoResponse, Response}, /// response::{IntoResponse, Response},
/// Form, Json, RequestExt, /// Form, Json, RequestExt,
/// }; /// };
@@ -42,7 +41,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// { /// {
/// type Rejection = Response; /// type Rejection = Response;
/// ///
/// async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { /// async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
/// let content_type = req /// let content_type = req
/// .headers() /// .headers()
/// .get(CONTENT_TYPE) /// .get(CONTENT_TYPE)
@@ -87,8 +86,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// use axum::{ /// use axum::{
/// async_trait, /// async_trait,
/// body::Body, /// body::Body,
/// extract::{FromRef, FromRequest}, /// extract::{Request, FromRef, FromRequest},
/// http::Request,
/// RequestExt, /// RequestExt,
/// }; /// };
/// ///
@@ -104,7 +102,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// { /// {
/// type Rejection = std::convert::Infallible; /// type Rejection = std::convert::Infallible;
/// ///
/// async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { /// async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
/// let requires_state = req.extract_with_state::<RequiresState, _, _>(state).await?; /// let requires_state = req.extract_with_state::<RequiresState, _, _>(state).await?;
/// ///
/// Ok(Self { requires_state }) /// Ok(Self { requires_state })
@@ -122,7 +120,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// { /// {
/// // ... /// // ...
/// # type Rejection = std::convert::Infallible; /// # type Rejection = std::convert::Infallible;
/// # async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { /// # async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
/// # todo!() /// # todo!()
/// # } /// # }
/// } /// }
@@ -141,9 +139,8 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// ``` /// ```
/// use axum::{ /// use axum::{
/// async_trait, /// async_trait,
/// extract::FromRequest, /// extract::{Request, FromRequest},
/// headers::{authorization::Bearer, Authorization}, /// headers::{authorization::Bearer, Authorization},
/// http::Request,
/// response::{IntoResponse, Response}, /// response::{IntoResponse, Response},
/// body::Body, /// body::Body,
/// Json, RequestExt, TypedHeader, /// Json, RequestExt, TypedHeader,
@@ -163,7 +160,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// { /// {
/// type Rejection = Response; /// type Rejection = Response;
/// ///
/// async fn from_request(mut req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { /// async fn from_request(mut req: Request, _state: &S) -> Result<Self, Self::Rejection> {
/// let TypedHeader(auth_header) = req /// let TypedHeader(auth_header) = req
/// .extract_parts::<TypedHeader<Authorization<Bearer>>>() /// .extract_parts::<TypedHeader<Authorization<Bearer>>>()
/// .await /// .await
@@ -194,8 +191,8 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// ``` /// ```
/// use axum::{ /// use axum::{
/// async_trait, /// async_trait,
/// extract::{FromRef, FromRequest, FromRequestParts}, /// extract::{Request, FromRef, FromRequest, FromRequestParts},
/// http::{request::Parts, Request}, /// http::request::Parts,
/// response::{IntoResponse, Response}, /// response::{IntoResponse, Response},
/// body::Body, /// body::Body,
/// Json, RequestExt, /// Json, RequestExt,
@@ -216,7 +213,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// { /// {
/// type Rejection = Response; /// type Rejection = Response;
/// ///
/// async fn from_request(mut req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { /// async fn from_request(mut req: Request, state: &S) -> Result<Self, Self::Rejection> {
/// let requires_state = req /// let requires_state = req
/// .extract_parts_with_state::<RequiresState, _>(state) /// .extract_parts_with_state::<RequiresState, _>(state)
/// .await /// .await
@@ -260,7 +257,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
/// Apply the [default body limit](crate::extract::DefaultBodyLimit). /// Apply the [default body limit](crate::extract::DefaultBodyLimit).
/// ///
/// If it is disabled, return the request as-is in `Err`. /// If it is disabled, return the request as-is in `Err`.
fn with_limited_body(self) -> Result<Request<Limited<Body>>, Request<Body>>; fn with_limited_body(self) -> Result<Request<Limited<Body>>, Request>;
/// Consumes the request, returning the body wrapped in [`Limited`] if a /// Consumes the request, returning the body wrapped in [`Limited`] if a
/// [default limit](crate::extract::DefaultBodyLimit) is in place, or not wrapped if the /// [default limit](crate::extract::DefaultBodyLimit) is in place, or not wrapped if the
@@ -268,7 +265,7 @@ pub trait RequestExt: sealed::Sealed + Sized {
fn into_limited_body(self) -> Result<Limited<Body>, Body>; fn into_limited_body(self) -> Result<Limited<Body>, Body>;
} }
impl RequestExt for Request<Body> { impl RequestExt for Request {
fn extract<E, M>(self) -> BoxFuture<'static, Result<E, E::Rejection>> fn extract<E, M>(self) -> BoxFuture<'static, Result<E, E::Rejection>>
where where
E: FromRequest<(), M> + 'static, E: FromRequest<(), M> + 'static,
@@ -321,7 +318,7 @@ impl RequestExt for Request<Body> {
}) })
} }
fn with_limited_body(self) -> Result<Request<Limited<Body>>, Request<Body>> { fn with_limited_body(self) -> Result<Request<Limited<Body>>, Request> {
// update docs in `axum-core/src/extract/default_body_limit.rs` and // update docs in `axum-core/src/extract/default_body_limit.rs` and
// `axum/src/docs/extract.md` if this changes // `axum/src/docs/extract.md` if this changes
const DEFAULT_LIMIT: usize = 2_097_152; // 2 mb const DEFAULT_LIMIT: usize = 2_097_152; // 2 mb
@@ -426,7 +423,7 @@ mod tests {
{ {
type Rejection = <String as FromRequest<()>>::Rejection; type Rejection = <String as FromRequest<()>>::Rejection;
async fn from_request(mut req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(mut req: Request, state: &S) -> Result<Self, Self::Rejection> {
let RequiresState(from_state) = req.extract_parts_with_state(state).await.unwrap(); let RequiresState(from_state) = req.extract_parts_with_state(state).await.unwrap();
let method = req.extract_parts().await.unwrap(); let method = req.extract_parts().await.unwrap();
let body = req.extract().await?; let body = req.extract().await?;
+4 -5
View File
@@ -30,22 +30,21 @@ use tower_layer::Layer;
/// Router, /// Router,
/// routing::post, /// routing::post,
/// body::Body, /// body::Body,
/// extract::{DefaultBodyLimit, RawBody}, /// extract::{Request, DefaultBodyLimit},
/// http::Request,
/// }; /// };
/// ///
/// let app = Router::new() /// let app = Router::new()
/// .route( /// .route(
/// "/", /// "/",
/// // even with `DefaultBodyLimit` the request body is still just `Body` /// // even with `DefaultBodyLimit` the request body is still just `Body`
/// post(|request: Request<Body>| async {}), /// post(|request: Request| async {}),
/// ) /// )
/// .layer(DefaultBodyLimit::max(1024)); /// .layer(DefaultBodyLimit::max(1024));
/// # let _: Router = app; /// # let _: Router = app;
/// ``` /// ```
/// ///
/// ``` /// ```
/// use axum::{Router, routing::post, body::Body, extract::RawBody, http::Request}; /// use axum::{Router, routing::post, body::Body, extract::Request};
/// use tower_http::limit::RequestBodyLimitLayer; /// use tower_http::limit::RequestBodyLimitLayer;
/// use http_body::Limited; /// use http_body::Limited;
/// ///
@@ -54,7 +53,7 @@ use tower_layer::Layer;
/// "/", /// "/",
/// // `RequestBodyLimitLayer` changes the request body type to `Limited<Body>` /// // `RequestBodyLimitLayer` changes the request body type to `Limited<Body>`
/// // extracting a different body type wont work /// // extracting a different body type wont work
/// post(|request: Request<Body>| async {}), /// post(|request: Request| async {}),
/// ) /// )
/// .layer(RequestBodyLimitLayer::new(1024)); /// .layer(RequestBodyLimitLayer::new(1024));
/// # let _: Router = app; /// # let _: Router = app;
+9 -5
View File
@@ -6,7 +6,7 @@
use crate::{body::Body, response::IntoResponse}; use crate::{body::Body, response::IntoResponse};
use async_trait::async_trait; use async_trait::async_trait;
use http::{request::Parts, Request}; use http::request::Parts;
use std::convert::Infallible; use std::convert::Infallible;
pub mod rejection; pub mod rejection;
@@ -19,6 +19,10 @@ mod tuple;
pub(crate) use self::default_body_limit::DefaultBodyLimitKind; pub(crate) use self::default_body_limit::DefaultBodyLimitKind;
pub use self::{default_body_limit::DefaultBodyLimit, from_ref::FromRef}; pub use self::{default_body_limit::DefaultBodyLimit, from_ref::FromRef};
/// Type alias for [`http::Request`] whose body type defaults to [`Body`], the most common body
/// type used with axum.
pub type Request<T = Body> = http::Request<T>;
mod private { mod private {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum ViaParts {} pub enum ViaParts {}
@@ -78,7 +82,7 @@ pub trait FromRequest<S, M = private::ViaRequest>: Sized {
type Rejection: IntoResponse; type Rejection: IntoResponse;
/// Perform the extraction. /// Perform the extraction.
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection>; async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection>;
} }
#[async_trait] #[async_trait]
@@ -89,7 +93,7 @@ where
{ {
type Rejection = <Self as FromRequestParts<S>>::Rejection; type Rejection = <Self as FromRequestParts<S>>::Rejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let (mut parts, _) = req.into_parts(); let (mut parts, _) = req.into_parts();
Self::from_request_parts(&mut parts, state).await Self::from_request_parts(&mut parts, state).await
} }
@@ -119,7 +123,7 @@ where
{ {
type Rejection = Infallible; type Rejection = Infallible;
async fn from_request(req: Request<Body>, state: &S) -> Result<Option<T>, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Option<T>, Self::Rejection> {
Ok(T::from_request(req, state).await.ok()) Ok(T::from_request(req, state).await.ok())
} }
} }
@@ -145,7 +149,7 @@ where
{ {
type Rejection = Infallible; type Rejection = Infallible;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
Ok(T::from_request(req, state).await) Ok(T::from_request(req, state).await)
} }
} }
+19 -7
View File
@@ -1,18 +1,18 @@
use super::{rejection::*, FromRequest, FromRequestParts}; use super::{rejection::*, FromRequest, FromRequestParts, Request};
use crate::{body::Body, RequestExt}; use crate::{body::Body, RequestExt};
use async_trait::async_trait; use async_trait::async_trait;
use bytes::Bytes; use bytes::Bytes;
use http::{request::Parts, HeaderMap, Method, Request, Uri, Version}; use http::{request::Parts, HeaderMap, Method, Uri, Version};
use std::convert::Infallible; use std::convert::Infallible;
#[async_trait] #[async_trait]
impl<S> FromRequest<S> for Request<Body> impl<S> FromRequest<S> for Request
where where
S: Send + Sync, S: Send + Sync,
{ {
type Rejection = Infallible; type Rejection = Infallible;
async fn from_request(req: Request<Body>, _: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejection> {
Ok(req) Ok(req)
} }
} }
@@ -77,7 +77,7 @@ where
{ {
type Rejection = BytesRejection; type Rejection = BytesRejection;
async fn from_request(req: Request<Body>, _: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejection> {
let bytes = match req.into_limited_body() { let bytes = match req.into_limited_body() {
Ok(limited_body) => crate::body::to_bytes(limited_body) Ok(limited_body) => crate::body::to_bytes(limited_body)
.await .await
@@ -98,7 +98,7 @@ where
{ {
type Rejection = StringRejection; type Rejection = StringRejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let bytes = Bytes::from_request(req, state) let bytes = Bytes::from_request(req, state)
.await .await
.map_err(|err| match err { .map_err(|err| match err {
@@ -122,7 +122,19 @@ where
{ {
type Rejection = Infallible; type Rejection = Infallible;
async fn from_request(req: Request<Body>, _: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejection> {
Ok(req.into_parts().0) Ok(req.into_parts().0)
} }
} }
#[async_trait]
impl<S> FromRequest<S> for Body
where
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejection> {
Ok(req.into_body())
}
}
+3 -4
View File
@@ -1,8 +1,7 @@
use super::{FromRequest, FromRequestParts}; use super::{FromRequest, FromRequestParts, Request};
use crate::body::Body;
use crate::response::{IntoResponse, Response}; use crate::response::{IntoResponse, Response};
use async_trait::async_trait; use async_trait::async_trait;
use http::request::{Parts, Request}; use http::request::Parts;
use std::convert::Infallible; use std::convert::Infallible;
#[async_trait] #[async_trait]
@@ -57,7 +56,7 @@ macro_rules! impl_from_request {
{ {
type Rejection = Response; type Rejection = Response;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let (mut parts, body) = req.into_parts(); let (mut parts, body) = req.into_parts();
$( $(
+19 -13
View File
@@ -1,5 +1,5 @@
use super::{IntoResponseParts, Response, ResponseParts}; use super::{IntoResponseParts, Response, ResponseParts};
use crate::{body, BoxError}; use crate::{body::Body, BoxError};
use bytes::{buf::Chain, Buf, Bytes, BytesMut}; use bytes::{buf::Chain, Buf, Bytes, BytesMut};
use http::{ use http::{
header::{self, HeaderMap, HeaderName, HeaderValue}, header::{self, HeaderMap, HeaderName, HeaderValue},
@@ -74,9 +74,9 @@ use std::{
/// body, /// body,
/// routing::get, /// routing::get,
/// response::{IntoResponse, Response}, /// response::{IntoResponse, Response},
/// body::Body,
/// Router, /// Router,
/// }; /// };
/// use http_body::Body;
/// use http::HeaderMap; /// use http::HeaderMap;
/// use bytes::Bytes; /// use bytes::Bytes;
/// use std::{ /// use std::{
@@ -89,7 +89,7 @@ use std::{
/// ///
/// // First implement `Body` for `MyBody`. This could for example use /// // First implement `Body` for `MyBody`. This could for example use
/// // some custom streaming protocol. /// // some custom streaming protocol.
/// impl Body for MyBody { /// impl http_body::Body for MyBody {
/// type Data = Bytes; /// type Data = Bytes;
/// type Error = Infallible; /// type Error = Infallible;
/// ///
@@ -113,7 +113,7 @@ use std::{
/// // Now we can implement `IntoResponse` directly for `MyBody` /// // Now we can implement `IntoResponse` directly for `MyBody`
/// impl IntoResponse for MyBody { /// impl IntoResponse for MyBody {
/// fn into_response(self) -> Response { /// fn into_response(self) -> Response {
/// Response::new(body::boxed(self)) /// Response::new(Body::new(self))
/// } /// }
/// } /// }
/// ///
@@ -165,25 +165,31 @@ where
B::Error: Into<BoxError>, B::Error: Into<BoxError>,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
self.map(body::boxed) self.map(Body::new)
} }
} }
impl IntoResponse for http::response::Parts { impl IntoResponse for http::response::Parts {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::from_parts(self, body::boxed(Empty::new())) Response::from_parts(self, Body::empty())
} }
} }
impl IntoResponse for Full<Bytes> { impl IntoResponse for Full<Bytes> {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
} }
} }
impl IntoResponse for Empty<Bytes> { impl IntoResponse for Empty<Bytes> {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
}
}
impl IntoResponse for Body {
fn into_response(self) -> Response {
Response::new(self)
} }
} }
@@ -192,7 +198,7 @@ where
E: Into<BoxError> + 'static, E: Into<BoxError> + 'static,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
} }
} }
@@ -201,7 +207,7 @@ where
E: Into<BoxError> + 'static, E: Into<BoxError> + 'static,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
} }
} }
@@ -212,7 +218,7 @@ where
B::Error: Into<BoxError>, B::Error: Into<BoxError>,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
} }
} }
@@ -223,7 +229,7 @@ where
E: Into<BoxError>, E: Into<BoxError>,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
} }
} }
@@ -274,7 +280,7 @@ where
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
let (first, second) = self.into_inner(); let (first, second) = self.into_inner();
let mut res = Response::new(body::boxed(BytesChainBody { let mut res = Response::new(Body::new(BytesChainBody {
first: Some(first), first: Some(first),
second: Some(second), second: Some(second),
})); }));
+3 -3
View File
@@ -4,7 +4,7 @@
//! //!
//! [`axum::response`]: https://docs.rs/axum/latest/axum/response/index.html //! [`axum::response`]: https://docs.rs/axum/latest/axum/response/index.html
use crate::body::BoxBody; use crate::body::Body;
mod append_headers; mod append_headers;
mod into_response; mod into_response;
@@ -16,9 +16,9 @@ pub use self::{
into_response_parts::{IntoResponseParts, ResponseParts, TryIntoHeaderError}, into_response_parts::{IntoResponseParts, ResponseParts, TryIntoHeaderError},
}; };
/// Type alias for [`http::Response`] whose body type defaults to [`BoxBody`], the most common body /// Type alias for [`http::Response`] whose body type defaults to [`Body`], the most common body
/// type used with axum. /// type used with axum.
pub type Response<T = BoxBody> = http::Response<T>; pub type Response<T = Body> = http::Response<T>;
/// An [`IntoResponse`]-based result type that uses [`ErrorResponse`] as the error type. /// An [`IntoResponse`]-based result type that uses [`ErrorResponse`] as the error type.
/// ///
-1
View File
@@ -22,7 +22,6 @@ use std::ops::{Deref, DerefMut};
/// use axum::{ /// use axum::{
/// async_trait, /// async_trait,
/// extract::FromRequestParts, /// extract::FromRequestParts,
/// body::BoxBody,
/// response::{IntoResponse, Response}, /// response::{IntoResponse, Response},
/// http::{StatusCode, request::Parts}, /// http::{StatusCode, request::Parts},
/// }; /// };
+3 -4
View File
@@ -1,11 +1,10 @@
use axum::{ use axum::{
async_trait, async_trait,
body::Body, extract::{rejection::RawFormRejection, FromRequest, RawForm, Request},
extract::{rejection::RawFormRejection, FromRequest, RawForm},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
Error, RequestExt, Error, RequestExt,
}; };
use http::{Request, StatusCode}; use http::StatusCode;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use std::{fmt, ops::Deref}; use std::{fmt, ops::Deref};
@@ -59,7 +58,7 @@ where
{ {
type Rejection = FormRejection; type Rejection = FormRejection;
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
let RawForm(bytes) = req let RawForm(bytes) = req
.extract() .extract()
.await .await
+3 -4
View File
@@ -1,9 +1,7 @@
use axum::async_trait; use axum::async_trait;
use axum::body::Body; use axum::extract::{FromRequest, FromRequestParts, Request};
use axum::extract::{FromRequest, FromRequestParts};
use axum::response::IntoResponse; use axum::response::IntoResponse;
use http::request::Parts; use http::request::Parts;
use http::Request;
use std::fmt::Debug; use std::fmt::Debug;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@@ -118,7 +116,7 @@ where
{ {
type Rejection = R; type Rejection = R;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let extractor = E::from_request(req, state).await?; let extractor = E::from_request(req, state).await?;
Ok(WithRejection(extractor, PhantomData)) Ok(WithRejection(extractor, PhantomData))
} }
@@ -141,6 +139,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use axum::body::Body;
use axum::extract::FromRequestParts; use axum::extract::FromRequestParts;
use axum::http::Request; use axum::http::Request;
use axum::response::Response; use axum::response::Response;
+2 -1
View File
@@ -1,6 +1,7 @@
//! Additional handler utilities. //! Additional handler utilities.
use axum::body::Body; use axum::body::Body;
use axum::extract::Request;
use axum::{ use axum::{
extract::FromRequest, extract::FromRequest,
handler::Handler, handler::Handler,
@@ -174,7 +175,7 @@ where
{ {
type Future = BoxFuture<'static, Response>; type Future = BoxFuture<'static, Response>;
fn call(self, req: http::Request<Body>, state: S) -> Self::Future { fn call(self, req: Request, state: S) -> Self::Future {
let req = req.map(Body::new); let req = req.map(Body::new);
Box::pin(async move { Box::pin(async move {
match T::from_request(req, &state).await { match T::from_request(req, &state).await {
+2 -4
View File
@@ -1,10 +1,8 @@
use super::HandlerCallWithExtractors; use super::HandlerCallWithExtractors;
use crate::either::Either; use crate::either::Either;
use axum::{ use axum::{
body::Body, extract::{FromRequest, FromRequestParts, Request},
extract::{FromRequest, FromRequestParts},
handler::Handler, handler::Handler,
http::Request,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
}; };
use futures_util::future::{BoxFuture, Either as EitherFuture, FutureExt, Map}; use futures_util::future::{BoxFuture, Either as EitherFuture, FutureExt, Map};
@@ -67,7 +65,7 @@ where
// this puts `futures_util` in our public API but thats fine in axum-extra // this puts `futures_util` in our public API but thats fine in axum-extra
type Future = BoxFuture<'static, Response>; type Future = BoxFuture<'static, Response>;
fn call(self, req: Request<Body>, state: S) -> Self::Future { fn call(self, req: Request, state: S) -> Self::Future {
Box::pin(async move { Box::pin(async move {
let (mut parts, body) = req.into_parts(); let (mut parts, body) = req.into_parts();
+2 -3
View File
@@ -3,13 +3,12 @@
use axum::{ use axum::{
async_trait, async_trait,
body::Body, body::Body,
extract::FromRequest, extract::{FromRequest, Request},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
BoxError, BoxError,
}; };
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use futures_util::stream::{BoxStream, Stream, TryStream, TryStreamExt}; use futures_util::stream::{BoxStream, Stream, TryStream, TryStreamExt};
use http::Request;
use pin_project_lite::pin_project; use pin_project_lite::pin_project;
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use std::{ use std::{
@@ -108,7 +107,7 @@ where
{ {
type Rejection = Infallible; type Rejection = Infallible;
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
// `Stream::lines` isn't a thing so we have to convert it into an `AsyncRead` // `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` // so we can call `AsyncRead::lines` and then convert it back to a `Stream`
let body = req.into_body(); let body = req.into_body();
+12 -13
View File
@@ -2,12 +2,11 @@
use axum::{ use axum::{
async_trait, async_trait,
body::Body, extract::{rejection::BytesRejection, FromRequest, Request},
extract::{rejection::BytesRejection, FromRequest},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
}; };
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use http::{Request, StatusCode}; use http::StatusCode;
use prost::Message; use prost::Message;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@@ -104,7 +103,7 @@ where
{ {
type Rejection = ProtobufRejection; type Rejection = ProtobufRejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let mut bytes = Bytes::from_request(req, state).await?; let mut bytes = Bytes::from_request(req, state).await?;
match T::decode(&mut bytes) { match T::decode(&mut bytes) {
@@ -286,16 +285,16 @@ mod tests {
result: String, result: String,
} }
let app = Router::new().route( #[axum::debug_handler]
"/", async fn handler(input: Protobuf<Input>) -> Protobuf<Output> {
post(|input: Protobuf<Input>| async move { let output = Output {
let output = Output { result: input.foo.to_owned(),
result: input.foo.to_owned(), };
};
Protobuf(output) Protobuf(output)
}), }
);
let app = Router::new().route("/", post(handler));
let input = Input { let input = Input {
foo: "bar".to_owned(), foo: "bar".to_owned(),
+3 -4
View File
@@ -1,8 +1,7 @@
//! Additional types for defining routes. //! Additional types for defining routes.
use axum::{ use axum::{
body::Body, extract::Request,
http::Request,
response::{IntoResponse, Redirect, Response}, response::{IntoResponse, Redirect, Response},
routing::{any, MethodRouter}, routing::{any, MethodRouter},
Router, Router,
@@ -166,7 +165,7 @@ pub trait RouterExt<S>: sealed::Sealed {
/// This works like [`RouterExt::route_with_tsr`] but accepts any [`Service`]. /// This works like [`RouterExt::route_with_tsr`] but accepts any [`Service`].
fn route_service_with_tsr<T>(self, path: &str, service: T) -> Self fn route_service_with_tsr<T>(self, path: &str, service: T) -> Self
where where
T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T: Service<Request, Error = Infallible> + Clone + Send + 'static,
T::Response: IntoResponse, T::Response: IntoResponse,
T::Future: Send + 'static, T::Future: Send + 'static,
Self: Sized; Self: Sized;
@@ -269,7 +268,7 @@ where
#[track_caller] #[track_caller]
fn route_service_with_tsr<T>(mut self, path: &str, service: T) -> Self fn route_service_with_tsr<T>(mut self, path: &str, service: T) -> Self
where where
T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T: Service<Request, Error = Infallible> + Clone + Send + 'static,
T::Response: IntoResponse, T::Response: IntoResponse,
T::Future: Send + 'static, T::Future: Send + 'static,
Self: Sized, Self: Sized,
+1
View File
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
request-consuming extractors ([#1826]) request-consuming extractors ([#1826])
[#1826]: https://github.com/tokio-rs/axum/pull/1826 [#1826]: https://github.com/tokio-rs/axum/pull/1826
[#1751]: https://github.com/tokio-rs/axum/pull/1751
# 0.3.5 (03. March, 2023) # 0.3.5 (03. March, 2023)
+1 -2
View File
@@ -43,10 +43,9 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn) -> TokenStream {
err.unwrap_or_else(|| { err.unwrap_or_else(|| {
let state_ty = state_ty.unwrap_or_else(|| syn::parse_quote!(())); let state_ty = state_ty.unwrap_or_else(|| syn::parse_quote!(()));
let check_input_order = check_input_order(&item_fn);
let check_future_send = check_future_send(&item_fn); let check_future_send = check_future_send(&item_fn);
if let Some(check_input_order) = check_input_order { if let Some(check_input_order) = check_input_order(&item_fn) {
quote! { quote! {
#check_input_order #check_input_order
#check_future_send #check_future_send
@@ -1,7 +1,6 @@
use axum::{ use axum::{
async_trait, async_trait,
extract::FromRequest, extract::{Request, FromRequest},
http::Request,
}; };
use axum_macros::debug_handler; use axum_macros::debug_handler;
@@ -14,7 +13,7 @@ where
{ {
type Rejection = (); type Rejection = ();
async fn from_request(_req: Request<axum::body::Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::Rejection> {
unimplemented!() unimplemented!()
} }
} }
@@ -1,5 +1,5 @@
error: Handlers must only take owned values error: Handlers must only take owned values
--> tests/debug_handler/fail/extract_self_mut.rs:24:22 --> tests/debug_handler/fail/extract_self_mut.rs:23:22
| |
24 | async fn handler(&mut self) {} 23 | async fn handler(&mut self) {}
| ^^^^^^^^^ | ^^^^^^^^^
@@ -1,7 +1,6 @@
use axum::{ use axum::{
async_trait, async_trait,
extract::FromRequest, extract::{Request, FromRequest},
http::Request,
}; };
use axum_macros::debug_handler; use axum_macros::debug_handler;
@@ -14,7 +13,7 @@ where
{ {
type Rejection = (); type Rejection = ();
async fn from_request(_req: Request<axum::body::Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::Rejection> {
unimplemented!() unimplemented!()
} }
} }
@@ -1,5 +1,5 @@
error: Handlers must only take owned values error: Handlers must only take owned values
--> tests/debug_handler/fail/extract_self_ref.rs:24:22 --> tests/debug_handler/fail/extract_self_ref.rs:23:22
| |
24 | async fn handler(&self) {} 23 | async fn handler(&self) {}
| ^^^^^ | ^^^^^
@@ -1,7 +1,7 @@
use axum::{body::Body, extract::Extension, http::Request}; use axum::extract::{Extension, Request};
use axum_macros::debug_handler; use axum_macros::debug_handler;
#[debug_handler] #[debug_handler]
async fn handler(_: Extension<String>, _: Request<Body>) {} async fn handler(_: Extension<String>, _: Request) {}
fn main() {} fn main() {}
@@ -1,7 +1,6 @@
use axum::{ use axum::{
async_trait, async_trait,
extract::FromRequest, extract::{Request, FromRequest},
http::Request,
}; };
use axum_macros::debug_handler; use axum_macros::debug_handler;
@@ -14,7 +13,7 @@ where
{ {
type Rejection = (); type Rejection = ();
async fn from_request(_req: Request<axum::body::Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::Rejection> {
unimplemented!() unimplemented!()
} }
} }
@@ -26,7 +25,7 @@ where
{ {
type Rejection = (); type Rejection = ();
async fn from_request(_req: Request<axum::body::Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::Rejection> {
unimplemented!() unimplemented!()
} }
} }
@@ -1,7 +1,6 @@
use axum_macros::debug_handler; use axum_macros::debug_handler;
use axum::extract::{FromRef, FromRequest}; use axum::extract::{Request, FromRef, FromRequest};
use axum::async_trait; use axum::async_trait;
use axum::http::Request;
#[debug_handler(state = AppState)] #[debug_handler(state = AppState)]
async fn handler(_: A) {} async fn handler(_: A) {}
@@ -19,7 +18,7 @@ where
{ {
type Rejection = (); type Rejection = ();
async fn from_request(_req: Request<axum::body::Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::Rejection> {
unimplemented!() unimplemented!()
} }
} }
@@ -1,8 +1,8 @@
use axum_macros::debug_handler; use axum_macros::debug_handler;
use axum::{extract::State, http::Request}; use axum::{extract::State, extract::Request};
#[debug_handler(state = AppState)] #[debug_handler(state = AppState)]
async fn handler(_: State<AppState>, _: Request<axum::body::Body>) {} async fn handler(_: State<AppState>, _: Request) {}
#[derive(Clone)] #[derive(Clone)]
struct AppState; struct AppState;
@@ -1,7 +1,7 @@
use axum::{ use axum::{
async_trait, async_trait,
extract::{rejection::ExtensionRejection, FromRequest}, extract::{Request, rejection::ExtensionRejection, FromRequest},
http::{StatusCode, Request}, http::StatusCode,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::get, routing::get,
body::Body, body::Body,
@@ -35,7 +35,7 @@ where
// this rejection doesn't implement `Display` and `Error` // this rejection doesn't implement `Display` and `Error`
type Rejection = (StatusCode, String); type Rejection = (StatusCode, String);
async fn from_request(_req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::Rejection> {
todo!() todo!()
} }
} }
+16 -5
View File
@@ -8,18 +8,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
# Unreleased # Unreleased
- **breaking:** The following types/traits are no longer generic over the request body - **breaking:** The following types/traits are no longer generic over the request body
(i.e. the `B` type param has been removed) ([#1751]): (i.e. the `B` type param has been removed) ([#1751] and [#1789]):
- `FromRequest`
- `FromRequestParts` - `FromRequestParts`
- `Handler` - `FromRequest`
- `HandlerService` - `HandlerService`
- `HandlerWithoutStateExt` - `HandlerWithoutStateExt`
- `Layered` - `Handler`
- `LayeredFuture` - `LayeredFuture`
- `Layered`
- `MethodRouter` - `MethodRouter`
- `Next`
- `RequestExt` - `RequestExt`
- `Route`
- `RouteFuture` - `RouteFuture`
- `Route`
- `Router` - `Router`
- **breaking:** axum no longer re-exports `hyper::Body` as that type is removed - **breaking:** axum no longer re-exports `hyper::Body` as that type is removed
in hyper 1.0. Instead axum has its own body type at `axum::body::Body` ([#1751]) in hyper 1.0. Instead axum has its own body type at `axum::body::Body` ([#1751])
@@ -28,6 +29,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **breaking:** Change `sse::Event::json_data` to use `axum_core::Error` as its error type ([#1762]) - **breaking:** Change `sse::Event::json_data` to use `axum_core::Error` as its error type ([#1762])
- **breaking:** Rename `DefaultOnFailedUpdgrade` to `DefaultOnFailedUpgrade` ([#1664]) - **breaking:** Rename `DefaultOnFailedUpdgrade` to `DefaultOnFailedUpgrade` ([#1664])
- **breaking:** Rename `OnFailedUpdgrade` to `OnFailedUpgrade` ([#1664]) - **breaking:** Rename `OnFailedUpdgrade` to `OnFailedUpgrade` ([#1664])
- **breaking:** Removed re-exports of `Empty` and `Full`. Use
`axum::body::Body::empty` and `axum::body::Body::from` respectively ([#1789])
- **breaking:** The response returned by `IntoResponse::into_response` must use
`axum::body::Body` as the body type. `axum::response::Response` does this
([#1789])
- **breaking:** Removed the `BoxBody` type alias and its `box_body`
constructor. Use `axum::body::Body::new` instead ([#1789])
- **breaking:** Remove `RawBody` extractor. `axum::body::Body` implements `FromRequest` directly ([#1789])
- **added:** Add `axum::extract::Request` type alias where the body is `axum::body::Body` ([#1789])
- **added:** Add `Router::as_service` and `Router::into_service` to workaround - **added:** Add `Router::as_service` and `Router::into_service` to workaround
type inference issues when calling `ServiceExt` methods on a `Router` ([#1835]) type inference issues when calling `ServiceExt` methods on a `Router` ([#1835])
@@ -35,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#1751]: https://github.com/tokio-rs/axum/pull/1751 [#1751]: https://github.com/tokio-rs/axum/pull/1751
[#1762]: https://github.com/tokio-rs/axum/pull/1762 [#1762]: https://github.com/tokio-rs/axum/pull/1762
[#1835]: https://github.com/tokio-rs/axum/pull/1835 [#1835]: https://github.com/tokio-rs/axum/pull/1835
[#1789]: https://github.com/tokio-rs/axum/pull/1789
# 0.6.12 (22. March, 2023) # 0.6.12 (22. March, 2023)
+2 -2
View File
@@ -1,10 +1,10 @@
//! HTTP body utilities. //! HTTP body utilities.
#[doc(no_inline)] #[doc(no_inline)]
pub use http_body::{Body as HttpBody, Empty, Full}; pub use http_body::Body as HttpBody;
#[doc(no_inline)] #[doc(no_inline)]
pub use bytes::Bytes; pub use bytes::Bytes;
#[doc(inline)] #[doc(inline)]
pub use axum_core::body::{boxed, Body, BoxBody}; pub use axum_core::body::Body;
+3 -2
View File
@@ -1,8 +1,9 @@
use crate::{ use crate::{
body::{self, Bytes, HttpBody}, body::{Bytes, HttpBody},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
BoxError, Error, BoxError, Error,
}; };
use axum_core::body::Body;
use futures_util::{ use futures_util::{
ready, ready,
stream::{self, TryStream}, stream::{self, TryStream},
@@ -93,7 +94,7 @@ where
S::Error: Into<BoxError>, S::Error: Into<BoxError>,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
Response::new(body::boxed(self)) Response::new(Body::new(self))
} }
} }
+6 -19
View File
@@ -1,7 +1,6 @@
use std::{convert::Infallible, fmt}; use std::{convert::Infallible, fmt};
use axum_core::body::Body; use crate::extract::Request;
use http::Request;
use tower::Service; use tower::Service;
use crate::{ use crate::{
@@ -37,11 +36,7 @@ where
})) }))
} }
pub(crate) fn call_with_state( pub(crate) fn call_with_state(self, request: Request, state: S) -> RouteFuture<Infallible> {
self,
request: Request<Body>,
state: S,
) -> RouteFuture<Infallible> {
self.0.call_with_state(request, state) self.0.call_with_state(request, state)
} }
} }
@@ -82,7 +77,7 @@ pub(crate) trait ErasedIntoRoute<S, E>: Send {
fn into_route(self: Box<Self>, state: S) -> Route<E>; fn into_route(self: Box<Self>, state: S) -> Route<E>;
fn call_with_state(self: Box<Self>, request: Request<Body>, state: S) -> RouteFuture<E>; fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E>;
} }
pub(crate) struct MakeErasedHandler<H, S> { pub(crate) struct MakeErasedHandler<H, S> {
@@ -103,11 +98,7 @@ where
(self.into_route)(self.handler, state) (self.into_route)(self.handler, state)
} }
fn call_with_state( fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
self: Box<Self>,
request: Request<Body>,
state: S,
) -> RouteFuture<Infallible> {
self.into_route(state).call(request) self.into_route(state).call(request)
} }
} }
@@ -141,11 +132,7 @@ where
(self.into_route)(self.router, state) (self.into_route)(self.router, state)
} }
fn call_with_state( fn call_with_state(mut self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
mut self: Box<Self>,
request: Request<Body>,
state: S,
) -> RouteFuture<Infallible> {
self.router.call_with_state(request, state) self.router.call_with_state(request, state)
} }
} }
@@ -184,7 +171,7 @@ where
(self.layer)(self.inner.into_route(state)) (self.layer)(self.inner.into_route(state))
} }
fn call_with_state(self: Box<Self>, request: Request<Body>, state: S) -> RouteFuture<E2> { fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E2> {
(self.layer)(self.inner.into_route(state)).call(request) (self.layer)(self.inner.into_route(state)).call(request)
} }
} }
+17 -21
View File
@@ -57,10 +57,10 @@ Some commonly used extractors are:
```rust,no_run ```rust,no_run
use axum::{ use axum::{
extract::{Json, TypedHeader, Path, Extension, Query}, extract::{Request, Json, TypedHeader, Path, Extension, Query},
routing::post, routing::post,
headers::UserAgent, headers::UserAgent,
http::{Request, header::HeaderMap}, http::header::HeaderMap,
body::{Bytes, Body}, body::{Bytes, Body},
Router, Router,
}; };
@@ -91,7 +91,7 @@ async fn bytes(body: Bytes) {}
async fn json(Json(payload): Json<Value>) {} async fn json(Json(payload): Json<Value>) {}
// `Request` gives you the whole request for maximum control // `Request` gives you the whole request for maximum control
async fn request(request: Request<Body>) {} async fn request(request: Request) {}
// `Extension` extracts data from "request extensions" // `Extension` extracts data from "request extensions"
// This is commonly used to share state with handlers // This is commonly used to share state with handlers
@@ -463,7 +463,7 @@ If your extractor needs to consume the request body you must implement [`FromReq
```rust,no_run ```rust,no_run
use axum::{ use axum::{
async_trait, async_trait,
extract::FromRequest, extract::{Request, FromRequest},
response::{Response, IntoResponse}, response::{Response, IntoResponse},
body::{Bytes, Body}, body::{Bytes, Body},
routing::get, routing::get,
@@ -471,7 +471,6 @@ use axum::{
http::{ http::{
StatusCode, StatusCode,
header::{HeaderValue, USER_AGENT}, header::{HeaderValue, USER_AGENT},
Request,
}, },
}; };
@@ -485,7 +484,7 @@ where
{ {
type Rejection = Response; type Rejection = Response;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let body = Bytes::from_request(req, state) let body = Bytes::from_request(req, state)
.await .await
.map_err(IntoResponse::into_response)?; .map_err(IntoResponse::into_response)?;
@@ -516,8 +515,8 @@ wrapping another extractor:
use axum::{ use axum::{
Router, Router,
routing::get, routing::get,
extract::{FromRequest, FromRequestParts}, extract::{FromRequest, Request, FromRequestParts},
http::{Request, request::Parts}, http::request::Parts,
body::Body, body::Body,
async_trait, async_trait,
}; };
@@ -534,7 +533,7 @@ where
{ {
type Rejection = Infallible; type Rejection = Infallible;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
// ... // ...
# todo!() # todo!()
} }
@@ -644,20 +643,17 @@ Extractors can also be run from middleware:
```rust ```rust
use axum::{ use axum::{
middleware::{self, Next}, middleware::{self, Next},
extract::{TypedHeader, FromRequestParts}, extract::{TypedHeader, Request, FromRequestParts},
http::{Request, StatusCode}, http::StatusCode,
response::Response, response::Response,
headers::authorization::{Authorization, Bearer}, headers::authorization::{Authorization, Bearer},
RequestPartsExt, Router, RequestPartsExt, Router,
}; };
async fn auth_middleware<B>( async fn auth_middleware(
request: Request<B>, request: Request,
next: Next<B>, next: Next,
) -> Result<Response, StatusCode> ) -> Result<Response, StatusCode> {
where
B: Send,
{
// running extractors requires a `axum::http::request::Parts` // running extractors requires a `axum::http::request::Parts`
let (mut parts, body) = request.into_parts(); let (mut parts, body) = request.into_parts();
@@ -696,8 +692,8 @@ use axum::{
Router, Router,
body::Body, body::Body,
routing::get, routing::get,
extract::{FromRequest, FromRequestParts}, extract::{Request, FromRequest, FromRequestParts},
http::{Request, HeaderMap, request::Parts}, http::{HeaderMap, request::Parts},
async_trait, async_trait,
}; };
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
@@ -737,7 +733,7 @@ where
{ {
type Rejection = T::Rejection; type Rejection = T::Rejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let start = Instant::now(); let start = Instant::now();
let extractor = T::from_request(req, state).await?; let extractor = T::from_request(req, state).await?;
let duration = start.elapsed(); let duration = start.elapsed();
+9 -10
View File
@@ -223,7 +223,7 @@ A decent template for such a middleware could be:
use axum::{ use axum::{
response::Response, response::Response,
body::Body, body::Body,
http::Request, extract::Request,
}; };
use futures_util::future::BoxFuture; use futures_util::future::BoxFuture;
use tower::{Service, Layer}; use tower::{Service, Layer};
@@ -245,9 +245,9 @@ struct MyMiddleware<S> {
inner: S, inner: S,
} }
impl<S> Service<Request<Body>> for MyMiddleware<S> impl<S> Service<Request> for MyMiddleware<S>
where where
S: Service<Request<Body>, Response = Response> + Send + 'static, S: Service<Request, Response = Response> + Send + 'static,
S::Future: Send + 'static, S::Future: Send + 'static,
{ {
type Response = S::Response; type Response = S::Response;
@@ -259,7 +259,7 @@ where
self.inner.poll_ready(cx) self.inner.poll_ready(cx)
} }
fn call(&mut self, request: Request<Body>) -> Self::Future { fn call(&mut self, request: Request) -> Self::Future {
let future = self.inner.call(request); let future = self.inner.call(request);
Box::pin(async move { Box::pin(async move {
let response: Response = future.await?; let response: Response = future.await?;
@@ -406,8 +406,7 @@ use axum::{
routing::get, routing::get,
middleware::{self, Next}, middleware::{self, Next},
response::Response, response::Response,
extract::State, extract::{State, Request},
http::Request,
}; };
use tower::{Layer, Service}; use tower::{Layer, Service};
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@@ -477,17 +476,17 @@ State can be passed from middleware to handlers using [request extensions]:
```rust ```rust
use axum::{ use axum::{
Router, Router,
http::{Request, StatusCode}, http::StatusCode,
routing::get, routing::get,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
middleware::{self, Next}, middleware::{self, Next},
extract::Extension, extract::{Request, Extension},
}; };
#[derive(Clone)] #[derive(Clone)]
struct CurrentUser { /* ... */ } struct CurrentUser { /* ... */ }
async fn auth<B>(mut req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> { async fn auth(mut req: Request, next: Next) -> Result<Response, StatusCode> {
let auth_header = req.headers() let auth_header = req.headers()
.get(http::header::AUTHORIZATION) .get(http::header::AUTHORIZATION)
.and_then(|header| header.to_str().ok()); .and_then(|header| header.to_str().ok());
@@ -546,7 +545,7 @@ use axum::{
ServiceExt, // for `into_make_service` ServiceExt, // for `into_make_service`
response::Response, response::Response,
middleware::Next, middleware::Next,
http::Request, extract::Request,
}; };
fn rewrite_request_uri<B>(req: Request<B>) -> Request<B> { fn rewrite_request_uri<B>(req: Request<B>) -> Request<B> {
+3 -3
View File
@@ -171,15 +171,15 @@ Use [`Response`](crate::response::Response) for more low level control:
use axum::{ use axum::{
Json, Json,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
body::{Full, Bytes}, body::Body,
http::StatusCode, http::StatusCode,
}; };
async fn response() -> Response<Full<Bytes>> { async fn response() -> Response {
Response::builder() Response::builder()
.status(StatusCode::NOT_FOUND) .status(StatusCode::NOT_FOUND)
.header("x-foo", "custom header") .header("x-foo", "custom header")
.body(Full::from("not found")) .body(Body::from("not found"))
.unwrap() .unwrap()
} }
``` ```
+4 -4
View File
@@ -7,7 +7,8 @@ use axum::{
Router, Router,
body::Body, body::Body,
routing::{any_service, get_service}, routing::{any_service, get_service},
http::{Request, StatusCode}, extract::Request,
http::StatusCode,
error_handling::HandleErrorLayer, error_handling::HandleErrorLayer,
}; };
use tower_http::services::ServeFile; use tower_http::services::ServeFile;
@@ -22,7 +23,7 @@ let app = Router::new()
// Services whose response body is not `axum::body::BoxBody` // Services whose response body is not `axum::body::BoxBody`
// can be wrapped in `axum::routing::any_service` (or one of the other routing filters) // can be wrapped in `axum::routing::any_service` (or one of the other routing filters)
// to have the response body mapped // to have the response body mapped
any_service(service_fn(|_: Request<Body>| async { any_service(service_fn(|_: Request| async {
let res = Response::new(Body::from("Hi from `GET /`")); let res = Response::new(Body::from("Hi from `GET /`"));
Ok::<_, Infallible>(res) Ok::<_, Infallible>(res)
})) }))
@@ -31,9 +32,8 @@ let app = Router::new()
"/foo", "/foo",
// This service's response body is `axum::body::BoxBody` so // This service's response body is `axum::body::BoxBody` so
// it can be routed to directly. // it can be routed to directly.
service_fn(|req: Request<Body>| async move { service_fn(|req: Request| async move {
let body = Body::from(format!("Hi from `{} /foo`", req.method())); let body = Body::from(format!("Hi from `{} /foo`", req.method()));
let body = axum::body::boxed(body);
let res = Response::new(body); let res = Response::new(body);
Ok::<_, Infallible>(res) Ok::<_, Infallible>(res)
}) })
+3 -5
View File
@@ -35,8 +35,7 @@ use std::{collections::HashMap, sync::Arc};
/// ``` /// ```
/// use axum::{ /// use axum::{
/// Router, /// Router,
/// extract::MatchedPath, /// extract::{Request, MatchedPath},
/// http::Request,
/// routing::get, /// routing::get,
/// }; /// };
/// use tower_http::trace::TraceLayer; /// use tower_http::trace::TraceLayer;
@@ -65,13 +64,12 @@ use std::{collections::HashMap, sync::Arc};
/// Router, /// Router,
/// RequestExt, /// RequestExt,
/// routing::get, /// routing::get,
/// extract::{MatchedPath, rejection::MatchedPathRejection}, /// extract::{Request, MatchedPath, rejection::MatchedPathRejection},
/// middleware::map_request, /// middleware::map_request,
/// http::Request,
/// body::Body, /// body::Body,
/// }; /// };
/// ///
/// async fn access_matched_path(mut request: Request<Body>) -> Request<Body> { /// async fn access_matched_path(mut request: Request) -> Request {
/// // if `/foo/bar` is called this will be `Err(_)` since that matches /// // if `/foo/bar` is called this will be `Err(_)` since that matches
/// // a nested route /// // a nested route
/// let matched_path: Result<MatchedPath, MatchedPathRejection> = /// let matched_path: Result<MatchedPath, MatchedPathRejection> =
+1 -2
View File
@@ -17,7 +17,7 @@ mod request_parts;
mod state; mod state;
#[doc(inline)] #[doc(inline)]
pub use axum_core::extract::{DefaultBodyLimit, FromRef, FromRequest, FromRequestParts}; pub use axum_core::extract::{DefaultBodyLimit, FromRef, FromRequest, FromRequestParts, Request};
#[cfg(feature = "macros")] #[cfg(feature = "macros")]
pub use axum_macros::{FromRef, FromRequest, FromRequestParts}; pub use axum_macros::{FromRef, FromRequest, FromRequestParts};
@@ -29,7 +29,6 @@ pub use self::{
path::{Path, RawPathParams}, path::{Path, RawPathParams},
raw_form::RawForm, raw_form::RawForm,
raw_query::RawQuery, raw_query::RawQuery,
request_parts::RawBody,
state::State, state::State,
}; };
+3 -3
View File
@@ -2,7 +2,7 @@
//! //!
//! See [`Multipart`] for more details. //! See [`Multipart`] for more details.
use super::FromRequest; use super::{FromRequest, Request};
use crate::body::Bytes; use crate::body::Bytes;
use async_trait::async_trait; use async_trait::async_trait;
use axum_core::body::Body; use axum_core::body::Body;
@@ -10,7 +10,7 @@ use axum_core::response::{IntoResponse, Response};
use axum_core::RequestExt; use axum_core::RequestExt;
use futures_util::stream::Stream; use futures_util::stream::Stream;
use http::header::{HeaderMap, CONTENT_TYPE}; use http::header::{HeaderMap, CONTENT_TYPE};
use http::{Request, StatusCode}; use http::StatusCode;
use std::error::Error; use std::error::Error;
use std::{ use std::{
fmt, fmt,
@@ -63,7 +63,7 @@ where
{ {
type Rejection = MultipartRejection; type Rejection = MultipartRejection;
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
let boundary = parse_boundary(req.headers()).ok_or(InvalidBoundary)?; let boundary = parse_boundary(req.headers()).ok_or(InvalidBoundary)?;
let stream = match req.with_limited_body() { let stream = match req.with_limited_body() {
Ok(limited) => Body::new(limited), Ok(limited) => Body::new(limited),
+3 -3
View File
@@ -1,7 +1,7 @@
use async_trait::async_trait; use async_trait::async_trait;
use axum_core::{body::Body, extract::FromRequest}; use axum_core::extract::{FromRequest, Request};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use http::{Method, Request}; use http::Method;
use super::{ use super::{
has_content_type, has_content_type,
@@ -39,7 +39,7 @@ where
{ {
type Rejection = RawFormRejection; type Rejection = RawFormRejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
if req.method() == Method::GET { if req.method() == Method::GET {
let mut bytes = BytesMut::new(); let mut bytes = BytesMut::new();
+2 -46
View File
@@ -1,7 +1,6 @@
use super::{Extension, FromRequest, FromRequestParts}; use super::{Extension, FromRequestParts};
use crate::body::Body;
use async_trait::async_trait; use async_trait::async_trait;
use http::{request::Parts, Request, Uri}; use http::{request::Parts, Uri};
use std::convert::Infallible; use std::convert::Infallible;
/// Extractor that gets the original request URI regardless of nesting. /// Extractor that gets the original request URI regardless of nesting.
@@ -91,49 +90,6 @@ where
} }
} }
/// Extractor that extracts the raw request body.
///
/// Since extracting the raw request body requires consuming it, the `RawBody` extractor must be
/// *last* if there are multiple extractors in a handler. See ["the order of extractors"][order-of-extractors]
///
/// [order-of-extractors]: crate::extract#the-order-of-extractors
///
/// # Example
///
/// ```rust,no_run
/// use axum::{
/// extract::RawBody,
/// routing::get,
/// Router,
/// };
/// use futures_util::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)]
pub struct RawBody(pub Body);
#[async_trait]
impl<S> FromRequest<S> for RawBody
where
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
Ok(Self(req.into_body()))
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{extract::Extension, routing::get, test_helpers::*, Router}; use crate::{extract::Extension, routing::get, test_helpers::*, Router};
+3 -6
View File
@@ -96,12 +96,9 @@
use self::rejection::*; use self::rejection::*;
use super::FromRequestParts; use super::FromRequestParts;
use crate::{ use crate::{body::Bytes, response::Response, Error};
body::{self, Bytes},
response::Response,
Error,
};
use async_trait::async_trait; use async_trait::async_trait;
use axum_core::body::Body;
use futures_util::{ use futures_util::{
sink::{Sink, SinkExt}, sink::{Sink, SinkExt},
stream::{Stream, StreamExt}, stream::{Stream, StreamExt},
@@ -332,7 +329,7 @@ impl<F> WebSocketUpgrade<F> {
builder = builder.header(header::SEC_WEBSOCKET_PROTOCOL, protocol); builder = builder.header(header::SEC_WEBSOCKET_PROTOCOL, protocol);
} }
builder.body(body::boxed(body::Empty::new())).unwrap() builder.body(Body::empty()).unwrap()
} }
} }
+7 -6
View File
@@ -1,10 +1,10 @@
use crate::extract::Request;
use crate::extract::{rejection::*, FromRequest, RawForm}; use crate::extract::{rejection::*, FromRequest, RawForm};
use async_trait::async_trait; use async_trait::async_trait;
use axum_core::body::Body;
use axum_core::response::{IntoResponse, Response}; use axum_core::response::{IntoResponse, Response};
use axum_core::RequestExt; use axum_core::RequestExt;
use http::header::CONTENT_TYPE; use http::header::CONTENT_TYPE;
use http::{Request, StatusCode}; use http::StatusCode;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use std::ops::Deref; use std::ops::Deref;
@@ -71,7 +71,7 @@ where
{ {
type Rejection = FormRejection; type Rejection = FormRejection;
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
let is_get_or_head = let is_get_or_head =
req.method() == http::Method::GET || req.method() == http::Method::HEAD; req.method() == http::Method::GET || req.method() == http::Method::HEAD;
@@ -121,14 +121,15 @@ impl<T> Deref for Form<T> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use crate::{ use crate::{
body::Body,
routing::{on, MethodFilter}, routing::{on, MethodFilter},
test_helpers::TestClient, test_helpers::TestClient,
Router, Router,
}; };
use http::{header::CONTENT_TYPE, Method, Request};
use super::*;
use axum_core::body::Body;
use http::{Method, Request};
use mime::APPLICATION_WWW_FORM_URLENCODED; use mime::APPLICATION_WWW_FORM_URLENCODED;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::fmt::Debug;
+6 -7
View File
@@ -1,9 +1,8 @@
//! Handler future types. //! Handler future types.
use crate::body::Body;
use crate::response::Response; use crate::response::Response;
use axum_core::extract::Request;
use futures_util::future::Map; use futures_util::future::Map;
use http::Request;
use pin_project_lite::pin_project; use pin_project_lite::pin_project;
use std::{convert::Infallible, future::Future, pin::Pin, task::Context}; use std::{convert::Infallible, future::Future, pin::Pin, task::Context};
use tower::util::Oneshot; use tower::util::Oneshot;
@@ -22,19 +21,19 @@ pin_project! {
/// The response future for [`Layered`](super::Layered). /// The response future for [`Layered`](super::Layered).
pub struct LayeredFuture<S> pub struct LayeredFuture<S>
where where
S: Service<Request<Body>>, S: Service<Request>,
{ {
#[pin] #[pin]
inner: Map<Oneshot<S, Request<Body>>, fn(Result<S::Response, S::Error>) -> Response>, inner: Map<Oneshot<S, Request>, fn(Result<S::Response, S::Error>) -> Response>,
} }
} }
impl<S> LayeredFuture<S> impl<S> LayeredFuture<S>
where where
S: Service<Request<Body>>, S: Service<Request>,
{ {
pub(super) fn new( pub(super) fn new(
inner: Map<Oneshot<S, Request<Body>>, fn(Result<S::Response, S::Error>) -> Response>, inner: Map<Oneshot<S, Request>, fn(Result<S::Response, S::Error>) -> Response>,
) -> Self { ) -> Self {
Self { inner } Self { inner }
} }
@@ -42,7 +41,7 @@ where
impl<S> Future for LayeredFuture<S> impl<S> Future for LayeredFuture<S>
where where
S: Service<Request<Body>>, S: Service<Request>,
{ {
type Output = Response; type Output = Response;
+17 -19
View File
@@ -37,12 +37,10 @@
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
use crate::extract::connect_info::IntoMakeServiceWithConnectInfo; use crate::extract::connect_info::IntoMakeServiceWithConnectInfo;
use crate::{ use crate::{
extract::{FromRequest, FromRequestParts}, extract::{FromRequest, FromRequestParts, Request},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::IntoMakeService, routing::IntoMakeService,
}; };
use axum_core::body::Body;
use http::Request;
use std::{convert::Infallible, fmt, future::Future, marker::PhantomData, pin::Pin}; use std::{convert::Infallible, fmt, future::Future, marker::PhantomData, pin::Pin};
use tower::ServiceExt; use tower::ServiceExt;
use tower_layer::Layer; use tower_layer::Layer;
@@ -68,9 +66,8 @@ pub use self::service::HandlerService;
/// ``` /// ```
/// use tower::Service; /// use tower::Service;
/// use axum::{ /// use axum::{
/// extract::State, /// extract::{State, Request},
/// body::Body, /// body::Body,
/// http::Request,
/// handler::{HandlerWithoutStateExt, Handler}, /// handler::{HandlerWithoutStateExt, Handler},
/// }; /// };
/// ///
@@ -89,7 +86,7 @@ pub use self::service::HandlerService;
/// // helper to check that a value implements `Service` /// // helper to check that a value implements `Service`
/// fn assert_service<S>(service: S) /// fn assert_service<S>(service: S)
/// where /// where
/// S: Service<Request<Body>>, /// S: Service<Request>,
/// {} /// {}
/// ``` /// ```
#[doc = include_str!("../docs/debugging_handler_type_errors.md")] #[doc = include_str!("../docs/debugging_handler_type_errors.md")]
@@ -104,7 +101,7 @@ pub trait Handler<T, S>: Clone + Send + Sized + 'static {
type Future: Future<Output = Response> + Send + 'static; type Future: Future<Output = Response> + Send + 'static;
/// Call the handler with the given request. /// Call the handler with the given request.
fn call(self, req: Request<Body>, state: S) -> Self::Future; fn call(self, req: Request, state: S) -> Self::Future;
/// Apply a [`tower::Layer`] to the handler. /// Apply a [`tower::Layer`] to the handler.
/// ///
@@ -145,7 +142,7 @@ pub trait Handler<T, S>: Clone + Send + Sized + 'static {
fn layer<L>(self, layer: L) -> Layered<L, Self, T, S> fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
where where
L: Layer<HandlerService<Self, T, S>> + Clone, L: Layer<HandlerService<Self, T, S>> + Clone,
L::Service: Service<Request<Body>>, L::Service: Service<Request>,
{ {
Layered { Layered {
layer, layer,
@@ -168,7 +165,7 @@ where
{ {
type Future = Pin<Box<dyn Future<Output = Response> + Send>>; type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
fn call(self, _req: Request<Body>, _state: S) -> Self::Future { fn call(self, _req: Request, _state: S) -> Self::Future {
Box::pin(async move { self().await.into_response() }) Box::pin(async move { self().await.into_response() })
} }
} }
@@ -189,7 +186,7 @@ macro_rules! impl_handler {
{ {
type Future = Pin<Box<dyn Future<Output = Response> + Send>>; type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
fn call(self, req: Request<Body>, state: S) -> Self::Future { fn call(self, req: Request, state: S) -> Self::Future {
Box::pin(async move { Box::pin(async move {
let (mut parts, body) = req.into_parts(); let (mut parts, body) = req.into_parts();
let state = &state; let state = &state;
@@ -257,15 +254,15 @@ impl<H, S, T, L> Handler<T, S> for Layered<L, H, T, S>
where where
L: Layer<HandlerService<H, T, S>> + Clone + Send + 'static, L: Layer<HandlerService<H, T, S>> + Clone + Send + 'static,
H: Handler<T, S>, H: Handler<T, S>,
L::Service: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, L::Service: Service<Request, Error = Infallible> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse, <L::Service as Service<Request>>::Response: IntoResponse,
<L::Service as Service<Request<Body>>>::Future: Send, <L::Service as Service<Request>>::Future: Send,
T: 'static, T: 'static,
S: 'static, S: 'static,
{ {
type Future = future::LayeredFuture<L::Service>; type Future = future::LayeredFuture<L::Service>;
fn call(self, req: Request<Body>, state: S) -> Self::Future { fn call(self, req: Request, state: S) -> Self::Future {
use futures_util::future::{FutureExt, Map}; use futures_util::future::{FutureExt, Map};
let svc = self.handler.with_state(state); let svc = self.handler.with_state(state);
@@ -275,8 +272,8 @@ where
_, _,
fn( fn(
Result< Result<
<L::Service as Service<Request<Body>>>::Response, <L::Service as Service<Request>>::Response,
<L::Service as Service<Request<Body>>>::Error, <L::Service as Service<Request>>::Error,
>, >,
) -> _, ) -> _,
> = svc.oneshot(req).map(|result| match result { > = svc.oneshot(req).map(|result| match result {
@@ -339,7 +336,8 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::{body, extract::State, test_helpers::*}; use crate::{extract::State, test_helpers::*};
use axum_core::body::Body;
use http::StatusCode; use http::StatusCode;
use std::time::Duration; use std::time::Duration;
use tower_http::{ use tower_http::{
@@ -371,10 +369,10 @@ mod tests {
.layer(( .layer((
RequestBodyLimitLayer::new(1024), RequestBodyLimitLayer::new(1024),
TimeoutLayer::new(Duration::from_secs(10)), TimeoutLayer::new(Duration::from_secs(10)),
MapResponseBodyLayer::new(body::boxed), MapResponseBodyLayer::new(Body::new),
CompressionLayer::new(), CompressionLayer::new(),
)) ))
.layer(MapRequestBodyLayer::new(body::boxed)) .layer(MapRequestBodyLayer::new(Body::new))
.with_state("foo"); .with_state("foo");
let client = TestClient::new(svc); let client = TestClient::new(svc);
+4 -6
View File
@@ -1,13 +1,11 @@
use crate::extract::Request;
use crate::extract::{rejection::*, FromRequest}; use crate::extract::{rejection::*, FromRequest};
use async_trait::async_trait; use async_trait::async_trait;
use axum_core::{ use axum_core::response::{IntoResponse, Response};
body::Body,
response::{IntoResponse, Response},
};
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use http::{ use http::{
header::{self, HeaderMap, HeaderValue}, header::{self, HeaderMap, HeaderValue},
Request, StatusCode, StatusCode,
}; };
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@@ -107,7 +105,7 @@ where
{ {
type Rejection = JsonRejection; type Rejection = JsonRejection;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
if json_content_type(req.headers()) { if json_content_type(req.headers()) {
let bytes = Bytes::from_request(req, state).await?; let bytes = Bytes::from_request(req, state).await?;
let deserializer = &mut serde_json::Deserializer::from_slice(&bytes); let deserializer = &mut serde_json::Deserializer::from_slice(&bytes);
+28 -50
View File
@@ -1,9 +1,6 @@
use crate::body::{Body, Bytes, HttpBody};
use crate::response::{IntoResponse, Response}; use crate::response::{IntoResponse, Response};
use crate::BoxError; use axum_core::extract::{FromRequest, FromRequestParts, Request};
use axum_core::extract::{FromRequest, FromRequestParts};
use futures_util::future::BoxFuture; use futures_util::future::BoxFuture;
use http::Request;
use std::{ use std::{
any::type_name, any::type_name,
convert::Infallible, convert::Infallible,
@@ -23,7 +20,7 @@ use tower_service::Service;
/// ///
/// 1. Be an `async fn`. /// 1. Be an `async fn`.
/// 2. Take one or more [extractors] as the first arguments. /// 2. Take one or more [extractors] as the first arguments.
/// 3. Take [`Next<B>`](Next) as the final argument. /// 3. Take [`Next`](Next) as the final argument.
/// 4. Return something that implements [`IntoResponse`]. /// 4. Return something that implements [`IntoResponse`].
/// ///
/// Note that this function doesn't support extracting [`State`]. For that, use [`from_fn_with_state`]. /// Note that this function doesn't support extracting [`State`]. For that, use [`from_fn_with_state`].
@@ -33,15 +30,16 @@ use tower_service::Service;
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// Router, /// Router,
/// http::{self, Request}, /// http,
/// routing::get, /// routing::get,
/// response::Response, /// response::Response,
/// middleware::{self, Next}, /// middleware::{self, Next},
/// extract::Request,
/// }; /// };
/// ///
/// async fn my_middleware<B>( /// async fn my_middleware(
/// request: Request<B>, /// request: Request,
/// next: Next<B>, /// next: Next,
/// ) -> Response { /// ) -> Response {
/// // do something with `request`... /// // do something with `request`...
/// ///
@@ -63,23 +61,22 @@ use tower_service::Service;
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// Router, /// Router,
/// extract::TypedHeader, /// extract::{Request, TypedHeader},
/// http::StatusCode, /// http::StatusCode,
/// headers::authorization::{Authorization, Bearer}, /// headers::authorization::{Authorization, Bearer},
/// http::Request,
/// middleware::{self, Next}, /// middleware::{self, Next},
/// response::Response, /// response::Response,
/// routing::get, /// routing::get,
/// }; /// };
/// ///
/// async fn auth<B>( /// async fn auth(
/// // run the `TypedHeader` extractor /// // run the `TypedHeader` extractor
/// TypedHeader(auth): TypedHeader<Authorization<Bearer>>, /// TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
/// // you can also add more extractors here but the last /// // you can also add more extractors here but the last
/// // extractor must implement `FromRequest` which /// // extractor must implement `FromRequest` which
/// // `Request` does /// // `Request` does
/// request: Request<B>, /// request: Request,
/// next: Next<B>, /// next: Next,
/// ) -> Result<Response, StatusCode> { /// ) -> Result<Response, StatusCode> {
/// if token_is_valid(auth.token()) { /// if token_is_valid(auth.token()) {
/// let response = next.run(request).await; /// let response = next.run(request).await;
@@ -115,23 +112,23 @@ pub fn from_fn<F, T>(f: F) -> FromFnLayer<F, (), T> {
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// Router, /// Router,
/// http::{Request, StatusCode}, /// http::StatusCode,
/// routing::get, /// routing::get,
/// response::{IntoResponse, Response}, /// response::{IntoResponse, Response},
/// middleware::{self, Next}, /// middleware::{self, Next},
/// extract::State, /// extract::{Request, State},
/// }; /// };
/// ///
/// #[derive(Clone)] /// #[derive(Clone)]
/// struct AppState { /* ... */ } /// struct AppState { /* ... */ }
/// ///
/// async fn my_middleware<B>( /// async fn my_middleware(
/// State(state): State<AppState>, /// State(state): State<AppState>,
/// // you can add more extractors here but the last /// // you can add more extractors here but the last
/// // extractor must implement `FromRequest` which /// // extractor must implement `FromRequest` which
/// // `Request` does /// // `Request` does
/// request: Request<B>, /// request: Request,
/// next: Next<B>, /// next: Next,
/// ) -> Response { /// ) -> Response {
/// // do something with `request`... /// // do something with `request`...
/// ///
@@ -245,21 +242,19 @@ macro_rules! impl_service {
[$($ty:ident),*], $last:ident [$($ty:ident),*], $last:ident
) => { ) => {
#[allow(non_snake_case, unused_mut)] #[allow(non_snake_case, unused_mut)]
impl<F, Fut, Out, S, I, B, $($ty,)* $last> Service<Request<B>> for FromFn<F, S, I, ($($ty,)* $last,)> impl<F, Fut, Out, S, I, $($ty,)* $last> Service<Request> for FromFn<F, S, I, ($($ty,)* $last,)>
where where
F: FnMut($($ty,)* $last, Next<B>) -> Fut + Clone + Send + 'static, F: FnMut($($ty,)* $last, Next) -> Fut + Clone + Send + 'static,
$( $ty: FromRequestParts<S> + Send, )* $( $ty: FromRequestParts<S> + Send, )*
$last: FromRequest<S> + Send, $last: FromRequest<S> + Send,
Fut: Future<Output = Out> + Send + 'static, Fut: Future<Output = Out> + Send + 'static,
Out: IntoResponse + 'static, Out: IntoResponse + 'static,
I: Service<Request<B>, Error = Infallible> I: Service<Request, Error = Infallible>
+ Clone + Clone
+ Send + Send
+ 'static, + 'static,
I::Response: IntoResponse, I::Response: IntoResponse,
I::Future: Send + 'static, I::Future: Send + 'static,
B: HttpBody<Data = Bytes> + Send + 'static,
B::Error: Into<BoxError>,
S: Clone + Send + Sync + 'static, S: Clone + Send + Sync + 'static,
{ {
type Response = Response; type Response = Response;
@@ -270,9 +265,7 @@ macro_rules! impl_service {
self.inner.poll_ready(cx) self.inner.poll_ready(cx)
} }
fn call(&mut self, req: Request<B>) -> Self::Future { fn call(&mut self, req: Request) -> Self::Future {
let req = req.map(Body::new);
let not_ready_inner = self.inner.clone(); let not_ready_inner = self.inner.clone();
let ready_inner = std::mem::replace(&mut self.inner, not_ready_inner); let ready_inner = std::mem::replace(&mut self.inner, not_ready_inner);
@@ -330,13 +323,14 @@ where
} }
/// The remainder of a middleware stack, including the handler. /// The remainder of a middleware stack, including the handler.
pub struct Next<B> { #[derive(Debug, Clone)]
inner: BoxCloneService<Request<B>, Response, Infallible>, pub struct Next {
inner: BoxCloneService<Request, Response, Infallible>,
} }
impl<B> Next<B> { impl Next {
/// Execute the remaining middleware stack. /// Execute the remaining middleware stack.
pub async fn run(mut self, req: Request<B>) -> Response { pub async fn run(mut self, req: Request) -> Response {
match self.inner.call(req).await { match self.inner.call(req).await {
Ok(res) => res, Ok(res) => res,
Err(err) => match err {}, Err(err) => match err {},
@@ -344,23 +338,7 @@ impl<B> Next<B> {
} }
} }
impl<B> fmt::Debug for Next<B> { impl Service<Request> for Next {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FromFnLayer")
.field("inner", &self.inner)
.finish()
}
}
impl<B> Clone for Next<B> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<B> Service<Request<B>> for Next<B> {
type Response = Response; type Response = Response;
type Error = Infallible; type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>; type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
@@ -369,7 +347,7 @@ impl<B> Service<Request<B>> for Next<B> {
self.inner.poll_ready(cx) self.inner.poll_ready(cx)
} }
fn call(&mut self, req: Request<B>) -> Self::Future { fn call(&mut self, req: Request) -> Self::Future {
self.inner.call(req) self.inner.call(req)
} }
} }
@@ -402,7 +380,7 @@ mod tests {
#[crate::test] #[crate::test]
async fn basic() { async fn basic() {
async fn insert_header<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse { async fn insert_header(mut req: Request, next: Next) -> impl IntoResponse {
req.headers_mut() req.headers_mut()
.insert("x-axum-test", "ok".parse().unwrap()); .insert("x-axum-test", "ok".parse().unwrap());
+2 -2
View File
@@ -1,6 +1,6 @@
#![doc = include_str!("../docs/response.md")] #![doc = include_str!("../docs/response.md")]
use crate::body::{Bytes, Full}; use axum_core::body::Body;
use http::{header, HeaderValue}; use http::{header, HeaderValue};
mod redirect; mod redirect;
@@ -44,7 +44,7 @@ pub struct Html<T>(pub T);
impl<T> IntoResponse for Html<T> impl<T> IntoResponse for Html<T>
where where
T: Into<Full<Bytes>>, T: Into<Body>,
{ {
fn into_response(self) -> Response { fn into_response(self) -> Response {
( (
+4 -4
View File
@@ -32,7 +32,7 @@ use crate::{
BoxError, BoxError,
}; };
use axum_core::{ use axum_core::{
body, body::Body,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
}; };
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
@@ -104,7 +104,7 @@ where
(http::header::CONTENT_TYPE, mime::TEXT_EVENT_STREAM.as_ref()), (http::header::CONTENT_TYPE, mime::TEXT_EVENT_STREAM.as_ref()),
(http::header::CACHE_CONTROL, "no-cache"), (http::header::CACHE_CONTROL, "no-cache"),
], ],
body::boxed(Body { Body::new(SseBody {
event_stream: SyncWrapper::new(self.stream), event_stream: SyncWrapper::new(self.stream),
keep_alive: self.keep_alive.map(KeepAliveStream::new), keep_alive: self.keep_alive.map(KeepAliveStream::new),
}), }),
@@ -114,7 +114,7 @@ where
} }
pin_project! { pin_project! {
struct Body<S> { struct SseBody<S> {
#[pin] #[pin]
event_stream: SyncWrapper<S>, event_stream: SyncWrapper<S>,
#[pin] #[pin]
@@ -122,7 +122,7 @@ pin_project! {
} }
} }
impl<S, E> HttpBody for Body<S> impl<S, E> HttpBody for SseBody<S>
where where
S: Stream<Item = Result<Event, E>>, S: Stream<Item = Result<Event, E>>,
{ {
+1 -2
View File
@@ -46,12 +46,11 @@ opaque_future! {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::body::Body;
#[test] #[test]
fn traits() { fn traits() {
use crate::test_helpers::*; use crate::test_helpers::*;
assert_send::<IntoMakeService<Body>>(); assert_send::<IntoMakeService<()>>();
} }
} }
+39 -39
View File
@@ -8,11 +8,11 @@ use crate::{
boxed::BoxedIntoRoute, boxed::BoxedIntoRoute,
error_handling::{HandleError, HandleErrorLayer}, error_handling::{HandleError, HandleErrorLayer},
handler::Handler, handler::Handler,
http::{Method, Request, StatusCode}, http::{Method, StatusCode},
response::Response, response::Response,
routing::{future::RouteFuture, Fallback, MethodFilter, Route}, routing::{future::RouteFuture, Fallback, MethodFilter, Route},
}; };
use axum_core::{response::IntoResponse, BoxError}; use axum_core::{extract::Request, response::IntoResponse, BoxError};
use bytes::BytesMut; use bytes::BytesMut;
use std::{ use std::{
convert::Infallible, convert::Infallible,
@@ -34,7 +34,7 @@ macro_rules! top_level_service_fn {
/// ///
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// http::Request, /// extract::Request,
/// Router, /// Router,
/// routing::get_service, /// routing::get_service,
/// body::Body, /// body::Body,
@@ -42,7 +42,7 @@ macro_rules! top_level_service_fn {
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let service = tower::service_fn(|request: Request<Body>| async { /// let service = tower::service_fn(|request: Request| async {
/// Ok::<_, Infallible>(Response::new(Body::empty())) /// Ok::<_, Infallible>(Response::new(Body::empty()))
/// }); /// });
/// ///
@@ -80,7 +80,7 @@ macro_rules! top_level_service_fn {
$(#[$m])+ $(#[$m])+
pub fn $name<T, S>(svc: T) -> MethodRouter<S, T::Error> pub fn $name<T, S>(svc: T) -> MethodRouter<S, T::Error>
where where
T: Service<Request<Body>> + Clone + Send + 'static, T: Service<Request> + Clone + Send + 'static,
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
S: Clone, S: Clone,
@@ -161,7 +161,7 @@ macro_rules! chained_service_fn {
/// ///
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// http::Request, /// extract::Request,
/// Router, /// Router,
/// routing::post_service, /// routing::post_service,
/// body::Body, /// body::Body,
@@ -169,11 +169,11 @@ macro_rules! chained_service_fn {
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let service = tower::service_fn(|request: Request<Body>| async { /// let service = tower::service_fn(|request: Request| async {
/// Ok::<_, Infallible>(Response::new(Body::empty())) /// Ok::<_, Infallible>(Response::new(Body::empty()))
/// }); /// });
/// ///
/// let other_service = tower::service_fn(|request: Request<Body>| async { /// let other_service = tower::service_fn(|request: Request| async {
/// Ok::<_, Infallible>(Response::new(Body::empty())) /// Ok::<_, Infallible>(Response::new(Body::empty()))
/// }); /// });
/// ///
@@ -213,7 +213,7 @@ macro_rules! chained_service_fn {
#[track_caller] #[track_caller]
pub fn $name<T>(self, svc: T) -> Self pub fn $name<T>(self, svc: T) -> Self
where where
T: Service<Request<Body>, Error = E> T: Service<Request, Error = E>
+ Clone + Clone
+ Send + Send
+ 'static, + 'static,
@@ -301,7 +301,7 @@ top_level_service_fn!(trace_service, TRACE);
/// ///
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// http::Request, /// extract::Request,
/// routing::on, /// routing::on,
/// Router, /// Router,
/// body::Body, /// body::Body,
@@ -310,7 +310,7 @@ top_level_service_fn!(trace_service, TRACE);
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let service = tower::service_fn(|request: Request<Body>| async { /// let service = tower::service_fn(|request: Request| async {
/// Ok::<_, Infallible>(Response::new(Body::empty())) /// Ok::<_, Infallible>(Response::new(Body::empty()))
/// }); /// });
/// ///
@@ -322,7 +322,7 @@ top_level_service_fn!(trace_service, TRACE);
/// ``` /// ```
pub fn on_service<T, S>(filter: MethodFilter, svc: T) -> MethodRouter<S, T::Error> pub fn on_service<T, S>(filter: MethodFilter, svc: T) -> MethodRouter<S, T::Error>
where where
T: Service<Request<Body>> + Clone + Send + 'static, T: Service<Request> + Clone + Send + 'static,
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
S: Clone, S: Clone,
@@ -336,7 +336,7 @@ where
/// ///
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// http::Request, /// extract::Request,
/// Router, /// Router,
/// routing::any_service, /// routing::any_service,
/// body::Body, /// body::Body,
@@ -344,7 +344,7 @@ where
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let service = tower::service_fn(|request: Request<Body>| async { /// let service = tower::service_fn(|request: Request| async {
/// Ok::<_, Infallible>(Response::new(Body::empty())) /// Ok::<_, Infallible>(Response::new(Body::empty()))
/// }); /// });
/// ///
@@ -359,7 +359,7 @@ where
/// ///
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// http::Request, /// extract::Request,
/// Router, /// Router,
/// routing::any_service, /// routing::any_service,
/// body::Body, /// body::Body,
@@ -367,12 +367,12 @@ where
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let service = tower::service_fn(|request: Request<Body>| async { /// let service = tower::service_fn(|request: Request| async {
/// # Ok::<_, Infallible>(Response::new(Body::empty())) /// # Ok::<_, Infallible>(Response::new(Body::empty()))
/// // ... /// // ...
/// }); /// });
/// ///
/// let other_service = tower::service_fn(|request: Request<Body>| async { /// let other_service = tower::service_fn(|request: Request| async {
/// # Ok::<_, Infallible>(Response::new(Body::empty())) /// # Ok::<_, Infallible>(Response::new(Body::empty()))
/// // ... /// // ...
/// }); /// });
@@ -385,7 +385,7 @@ where
/// ``` /// ```
pub fn any_service<T, S>(svc: T) -> MethodRouter<S, T::Error> pub fn any_service<T, S>(svc: T) -> MethodRouter<S, T::Error>
where where
T: Service<Request<Body>> + Clone + Send + 'static, T: Service<Request> + Clone + Send + 'static,
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
S: Clone, S: Clone,
@@ -487,7 +487,7 @@ where
/// ///
/// ``` /// ```
/// use tower::Service; /// use tower::Service;
/// use axum::{routing::get, extract::State, body::Body, http::Request}; /// use axum::{routing::get, extract::{State, Request}, body::Body};
/// ///
/// // this `MethodRouter` doesn't require any state, i.e. the state is `()`, /// // this `MethodRouter` doesn't require any state, i.e. the state is `()`,
/// let method_router = get(|| async {}); /// let method_router = get(|| async {});
@@ -504,7 +504,7 @@ where
/// // helper to check that a value implements `Service` /// // helper to check that a value implements `Service`
/// fn assert_service<S>(service: S) /// fn assert_service<S>(service: S)
/// where /// where
/// S: Service<Request<Body>>, /// S: Service<Request>,
/// {} /// {}
/// ``` /// ```
#[must_use] #[must_use]
@@ -703,7 +703,7 @@ where
/// Create a default `MethodRouter` that will respond with `405 Method Not Allowed` to all /// Create a default `MethodRouter` that will respond with `405 Method Not Allowed` to all
/// requests. /// requests.
pub fn new() -> Self { pub fn new() -> Self {
let fallback = Route::new(service_fn(|_: Request<Body>| async { let fallback = Route::new(service_fn(|_: Request| async {
Ok(StatusCode::METHOD_NOT_ALLOWED.into_response()) Ok(StatusCode::METHOD_NOT_ALLOWED.into_response())
})); }));
@@ -744,7 +744,7 @@ where
/// ///
/// ```rust /// ```rust
/// use axum::{ /// use axum::{
/// http::Request, /// extract::Request,
/// Router, /// Router,
/// routing::{MethodFilter, on_service}, /// routing::{MethodFilter, on_service},
/// body::Body, /// body::Body,
@@ -752,7 +752,7 @@ where
/// use http::Response; /// use http::Response;
/// use std::convert::Infallible; /// use std::convert::Infallible;
/// ///
/// let service = tower::service_fn(|request: Request<Body>| async { /// let service = tower::service_fn(|request: Request| async {
/// Ok::<_, Infallible>(Response::new(Body::empty())) /// Ok::<_, Infallible>(Response::new(Body::empty()))
/// }); /// });
/// ///
@@ -765,7 +765,7 @@ where
#[track_caller] #[track_caller]
pub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self pub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self
where where
T: Service<Request<Body>, Error = E> + Clone + Send + 'static, T: Service<Request, Error = E> + Clone + Send + 'static,
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -897,7 +897,7 @@ where
#[doc = include_str!("../docs/method_routing/fallback.md")] #[doc = include_str!("../docs/method_routing/fallback.md")]
pub fn fallback_service<T>(mut self, svc: T) -> Self pub fn fallback_service<T>(mut self, svc: T) -> Self
where where
T: Service<Request<Body>, Error = E> + Clone + Send + 'static, T: Service<Request, Error = E> + Clone + Send + 'static,
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -909,10 +909,10 @@ where
pub fn layer<L, NewError>(self, layer: L) -> MethodRouter<S, NewError> pub fn layer<L, NewError>(self, layer: L) -> MethodRouter<S, NewError>
where where
L: Layer<Route<E>> + Clone + Send + 'static, L: Layer<Route<E>> + Clone + Send + 'static,
L::Service: Service<Request<Body>> + Clone + Send + 'static, L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request<Body>>>::Error: Into<NewError> + 'static, <L::Service as Service<Request>>::Error: Into<NewError> + 'static,
<L::Service as Service<Request<Body>>>::Future: Send + 'static, <L::Service as Service<Request>>::Future: Send + 'static,
E: 'static, E: 'static,
S: 'static, S: 'static,
NewError: 'static, NewError: 'static,
@@ -938,9 +938,9 @@ where
pub fn route_layer<L>(mut self, layer: L) -> MethodRouter<S, E> pub fn route_layer<L>(mut self, layer: L) -> MethodRouter<S, E>
where where
L: Layer<Route<E>> + Clone + Send + 'static, L: Layer<Route<E>> + Clone + Send + 'static,
L::Service: Service<Request<Body>, Error = E> + Clone + Send + 'static, L::Service: Service<Request, Error = E> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request<Body>>>::Future: Send + 'static, <L::Service as Service<Request>>::Future: Send + 'static,
E: 'static, E: 'static,
S: 'static, S: 'static,
{ {
@@ -1036,9 +1036,9 @@ where
pub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, Infallible> pub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, Infallible>
where where
F: Clone + Send + Sync + 'static, F: Clone + Send + Sync + 'static,
HandleError<Route<E>, F, T>: Service<Request<Body>, Error = Infallible>, HandleError<Route<E>, F, T>: Service<Request, Error = Infallible>,
<HandleError<Route<E>, F, T> as Service<Request<Body>>>::Future: Send, <HandleError<Route<E>, F, T> as Service<Request>>::Future: Send,
<HandleError<Route<E>, F, T> as Service<Request<Body>>>::Response: IntoResponse + Send, <HandleError<Route<E>, F, T> as Service<Request>>::Response: IntoResponse + Send,
T: 'static, T: 'static,
E: 'static, E: 'static,
S: 'static, S: 'static,
@@ -1051,7 +1051,7 @@ where
self self
} }
pub(crate) fn call_with_state(&mut self, req: Request<Body>, state: S) -> RouteFuture<E> { pub(crate) fn call_with_state(&mut self, req: Request, state: S) -> RouteFuture<E> {
macro_rules! call { macro_rules! call {
( (
$req:expr, $req:expr,
@@ -1256,7 +1256,7 @@ where
{ {
type Future = InfallibleRouteFuture; type Future = InfallibleRouteFuture;
fn call(mut self, req: Request<Body>, state: S) -> Self::Future { fn call(mut self, req: Request, state: S) -> Self::Future {
InfallibleRouteFuture::new(self.call_with_state(req, state)) InfallibleRouteFuture::new(self.call_with_state(req, state))
} }
} }
@@ -1284,7 +1284,7 @@ mod tests {
#[crate::test] #[crate::test]
async fn get_service_fn() { async fn get_service_fn() {
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> { async fn handle(_req: Request) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::from("ok"))) Ok(Response::new(Body::from("ok")))
} }
@@ -1545,7 +1545,7 @@ mod tests {
async fn call<S>(method: Method, svc: &mut S) -> (StatusCode, HeaderMap, String) async fn call<S>(method: Method, svc: &mut S) -> (StatusCode, HeaderMap, String)
where where
S: Service<Request<Body>, Error = Infallible>, S: Service<Request, Error = Infallible>,
S::Response: IntoResponse, S::Response: IntoResponse,
{ {
let request = Request::builder() let request = Request::builder()
+21 -19
View File
@@ -9,8 +9,10 @@ use crate::{
handler::Handler, handler::Handler,
util::try_downcast, util::try_downcast,
}; };
use axum_core::response::{IntoResponse, Response}; use axum_core::{
use http::Request; extract::Request,
response::{IntoResponse, Response},
};
use matchit::MatchError; use matchit::MatchError;
use std::{ use std::{
collections::HashMap, collections::HashMap,
@@ -152,7 +154,7 @@ where
#[doc = include_str!("../docs/routing/route_service.md")] #[doc = include_str!("../docs/routing/route_service.md")]
pub fn route_service<T>(self, path: &str, service: T) -> Self pub fn route_service<T>(self, path: &str, service: T) -> Self
where where
T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T: Service<Request, Error = Infallible> + Clone + Send + 'static,
T::Response: IntoResponse, T::Response: IntoResponse,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -203,7 +205,7 @@ where
#[track_caller] #[track_caller]
pub fn nest_service<T>(self, path: &str, svc: T) -> Self pub fn nest_service<T>(self, path: &str, svc: T) -> Self
where where
T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T: Service<Request, Error = Infallible> + Clone + Send + 'static,
T::Response: IntoResponse, T::Response: IntoResponse,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -213,7 +215,7 @@ where
#[track_caller] #[track_caller]
fn nest_endpoint<T>(mut self, mut path: &str, router_or_service: RouterOrService<S, T>) -> Self fn nest_endpoint<T>(mut self, mut path: &str, router_or_service: RouterOrService<S, T>) -> Self
where where
T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T: Service<Request, Error = Infallible> + Clone + Send + 'static,
T::Response: IntoResponse, T::Response: IntoResponse,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -299,10 +301,10 @@ where
pub fn layer<L>(self, layer: L) -> Router<S> pub fn layer<L>(self, layer: L) -> Router<S>
where where
L: Layer<Route> + Clone + Send + 'static, L: Layer<Route> + Clone + Send + 'static,
L::Service: Service<Request<Body>> + Clone + Send + 'static, L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request<Body>>>::Error: Into<Infallible> + 'static, <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
<L::Service as Service<Request<Body>>>::Future: Send + 'static, <L::Service as Service<Request>>::Future: Send + 'static,
{ {
let routes = self let routes = self
.routes .routes
@@ -328,10 +330,10 @@ where
pub fn route_layer<L>(self, layer: L) -> Self pub fn route_layer<L>(self, layer: L) -> Self
where where
L: Layer<Route> + Clone + Send + 'static, L: Layer<Route> + Clone + Send + 'static,
L::Service: Service<Request<Body>> + Clone + Send + 'static, L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request<Body>>>::Error: Into<Infallible> + 'static, <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
<L::Service as Service<Request<Body>>>::Future: Send + 'static, <L::Service as Service<Request>>::Future: Send + 'static,
{ {
if self.routes.is_empty() { if self.routes.is_empty() {
panic!( panic!(
@@ -372,7 +374,7 @@ where
/// See [`Router::fallback`] for more details. /// See [`Router::fallback`] for more details.
pub fn fallback_service<T>(mut self, svc: T) -> Self pub fn fallback_service<T>(mut self, svc: T) -> Self
where where
T: Service<Request<Body>, Error = Infallible> + Clone + Send + 'static, T: Service<Request, Error = Infallible> + Clone + Send + 'static,
T::Response: IntoResponse, T::Response: IntoResponse,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -411,7 +413,7 @@ where
pub(crate) fn call_with_state( pub(crate) fn call_with_state(
&mut self, &mut self,
mut req: Request<Body>, mut req: Request,
state: S, state: S,
) -> RouteFuture<Infallible> { ) -> RouteFuture<Infallible> {
#[cfg(feature = "original-uri")] #[cfg(feature = "original-uri")]
@@ -821,10 +823,10 @@ where
fn layer<L>(self, layer: L) -> Endpoint<S> fn layer<L>(self, layer: L) -> Endpoint<S>
where where
L: Layer<Route> + Clone + Send + 'static, L: Layer<Route> + Clone + Send + 'static,
L::Service: Service<Request<Body>> + Clone + Send + 'static, L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request<Body>>>::Error: Into<Infallible> + 'static, <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
<L::Service as Service<Request<Body>>>::Future: Send + 'static, <L::Service as Service<Request>>::Future: Send + 'static,
{ {
match self { match self {
Endpoint::MethodRouter(method_router) => { Endpoint::MethodRouter(method_router) => {
+15 -15
View File
@@ -1,12 +1,12 @@
use crate::{ use crate::{
body::{boxed, Body, Empty, HttpBody}, body::{Body, HttpBody},
response::Response, response::Response,
}; };
use axum_core::response::IntoResponse; use axum_core::{extract::Request, response::IntoResponse};
use bytes::Bytes; use bytes::Bytes;
use http::{ use http::{
header::{self, CONTENT_LENGTH}, header::{self, CONTENT_LENGTH},
HeaderMap, HeaderValue, Request, HeaderMap, HeaderValue,
}; };
use pin_project_lite::pin_project; use pin_project_lite::pin_project;
use std::{ use std::{
@@ -27,12 +27,12 @@ use tower_service::Service;
/// ///
/// You normally shouldn't need to care about this type. It's used in /// You normally shouldn't need to care about this type. It's used in
/// [`Router::layer`](super::Router::layer). /// [`Router::layer`](super::Router::layer).
pub struct Route<E = Infallible>(BoxCloneService<Request<Body>, Response, E>); pub struct Route<E = Infallible>(BoxCloneService<Request, Response, E>);
impl<E> Route<E> { impl<E> Route<E> {
pub(crate) fn new<T>(svc: T) -> Self pub(crate) fn new<T>(svc: T) -> Self
where where
T: Service<Request<Body>, Error = E> + Clone + Send + 'static, T: Service<Request, Error = E> + Clone + Send + 'static,
T::Response: IntoResponse + 'static, T::Response: IntoResponse + 'static,
T::Future: Send + 'static, T::Future: Send + 'static,
{ {
@@ -43,18 +43,18 @@ impl<E> Route<E> {
pub(crate) fn oneshot_inner( pub(crate) fn oneshot_inner(
&mut self, &mut self,
req: Request<Body>, req: Request,
) -> Oneshot<BoxCloneService<Request<Body>, Response, E>, Request<Body>> { ) -> Oneshot<BoxCloneService<Request, Response, E>, Request> {
self.0.clone().oneshot(req) self.0.clone().oneshot(req)
} }
pub(crate) fn layer<L, NewError>(self, layer: L) -> Route<NewError> pub(crate) fn layer<L, NewError>(self, layer: L) -> Route<NewError>
where where
L: Layer<Route<E>> + Clone + Send + 'static, L: Layer<Route<E>> + Clone + Send + 'static,
L::Service: Service<Request<Body>> + Clone + Send + 'static, L::Service: Service<Request> + Clone + Send + 'static,
<L::Service as Service<Request<Body>>>::Response: IntoResponse + 'static, <L::Service as Service<Request>>::Response: IntoResponse + 'static,
<L::Service as Service<Request<Body>>>::Error: Into<NewError> + 'static, <L::Service as Service<Request>>::Error: Into<NewError> + 'static,
<L::Service as Service<Request<Body>>>::Future: Send + 'static, <L::Service as Service<Request>>::Future: Send + 'static,
NewError: 'static, NewError: 'static,
{ {
let layer = ServiceBuilder::new() let layer = ServiceBuilder::new()
@@ -117,8 +117,8 @@ pin_project! {
Future { Future {
#[pin] #[pin]
future: Oneshot< future: Oneshot<
BoxCloneService<Request<Body>, Response, E>, BoxCloneService<Request, Response, E>,
Request<Body>, Request,
>, >,
}, },
Response { Response {
@@ -129,7 +129,7 @@ pin_project! {
impl<E> RouteFuture<E> { impl<E> RouteFuture<E> {
pub(crate) fn from_future( pub(crate) fn from_future(
future: Oneshot<BoxCloneService<Request<Body>, Response, E>, Request<Body>>, future: Oneshot<BoxCloneService<Request, Response, E>, Request>,
) -> Self { ) -> Self {
Self { Self {
kind: RouteFutureKind::Future { future }, kind: RouteFutureKind::Future { future },
@@ -173,7 +173,7 @@ impl<E> Future for RouteFuture<E> {
set_content_length(res.size_hint(), res.headers_mut()); set_content_length(res.size_hint(), res.headers_mut());
let res = if *this.strip_body { let res = if *this.strip_body {
res.map(|_| boxed(Empty::new())) res.map(|_| Body::empty())
} else { } else {
res res
}; };
+1 -1
View File
@@ -45,7 +45,7 @@ mod for_services {
async fn get_handles_head() { async fn get_handles_head() {
let app = Router::new().route( let app = Router::new().route(
"/", "/",
get_service(service_fn(|_req: Request<Body>| async move { get_service(service_fn(|_req: Request| async move {
Ok::<_, Infallible>( Ok::<_, Infallible>(
([("x-some-header", "foobar")], "you shouldn't see this").into_response(), ([("x-some-header", "foobar")], "you shouldn't see this").into_response(),
) )
+3 -3
View File
@@ -195,13 +195,13 @@ async fn services() {
let app = Router::new() let app = Router::new()
.route( .route(
"/foo", "/foo",
get_service(service_fn(|_: Request<Body>| async { get_service(service_fn(|_: Request| async {
Ok::<_, Infallible>(Response::new(Body::empty())) Ok::<_, Infallible>(Response::new(Body::empty()))
})), })),
) )
.merge(Router::new().route( .merge(Router::new().route(
"/bar", "/bar",
get_service(service_fn(|_: Request<Body>| async { get_service(service_fn(|_: Request| async {
Ok::<_, Infallible>(Response::new(Body::empty())) Ok::<_, Infallible>(Response::new(Body::empty()))
})), })),
)); ));
@@ -218,7 +218,7 @@ async fn services() {
async fn all_the_uris( async fn all_the_uris(
uri: Uri, uri: Uri,
OriginalUri(original_uri): OriginalUri, OriginalUri(original_uri): OriginalUri,
req: Request<Body>, req: Request,
) -> impl IntoResponse { ) -> impl IntoResponse {
Json(json!({ Json(json!({
"uri": uri.to_string(), "uri": uri.to_string(),
+21 -25
View File
@@ -1,15 +1,16 @@
use crate::{ use crate::{
body::{Body, Bytes, Empty}, body::{Body, Bytes},
error_handling::HandleErrorLayer, error_handling::HandleErrorLayer,
extract::{self, DefaultBodyLimit, FromRef, Path, State}, extract::{self, DefaultBodyLimit, FromRef, Path, State},
handler::{Handler, HandlerWithoutStateExt}, handler::{Handler, HandlerWithoutStateExt},
response::IntoResponse, response::{IntoResponse, Response},
routing::{delete, get, get_service, on, on_service, patch, patch_service, post, MethodFilter}, routing::{delete, get, get_service, on, on_service, patch, patch_service, post, MethodFilter},
test_helpers::*, test_helpers::*,
BoxError, Json, Router, BoxError, Json, Router,
}; };
use axum_core::extract::Request;
use futures_util::stream::StreamExt; use futures_util::stream::StreamExt;
use http::{header::ALLOW, header::CONTENT_LENGTH, HeaderMap, Request, Response, StatusCode, Uri}; use http::{header::ALLOW, header::CONTENT_LENGTH, HeaderMap, StatusCode, Uri};
use serde_json::json; use serde_json::json;
use std::{ use std::{
convert::Infallible, convert::Infallible,
@@ -30,15 +31,15 @@ mod nest;
#[crate::test] #[crate::test]
async fn hello_world() { async fn hello_world() {
async fn root(_: Request<Body>) -> &'static str { async fn root(_: Request) -> &'static str {
"Hello, World!" "Hello, World!"
} }
async fn foo(_: Request<Body>) -> &'static str { async fn foo(_: Request) -> &'static str {
"foo" "foo"
} }
async fn users_create(_: Request<Body>) -> &'static str { async fn users_create(_: Request) -> &'static str {
"users#create" "users#create"
} }
@@ -66,13 +67,12 @@ async fn routing() {
let app = Router::new() let app = Router::new()
.route( .route(
"/users", "/users",
get(|_: Request<Body>| async { "users#index" }) get(|_: Request| async { "users#index" }).post(|_: Request| async { "users#create" }),
.post(|_: Request<Body>| async { "users#create" }),
) )
.route("/users/:id", get(|_: Request<Body>| async { "users#show" })) .route("/users/:id", get(|_: Request| async { "users#show" }))
.route( .route(
"/users/:id/action", "/users/:id/action",
get(|_: Request<Body>| async { "users#action" }), get(|_: Request| async { "users#action" }),
); );
let client = TestClient::new(app); let client = TestClient::new(app);
@@ -102,12 +102,8 @@ async fn router_type_doesnt_change() {
let app: Router = Router::new() let app: Router = Router::new()
.route( .route(
"/", "/",
on(MethodFilter::GET, |_: Request<Body>| async { on(MethodFilter::GET, |_: Request| async { "hi from GET" })
"hi from GET" .on(MethodFilter::POST, |_: Request| async { "hi from POST" }),
})
.on(MethodFilter::POST, |_: Request<Body>| async {
"hi from POST"
}),
) )
.layer(tower_http::compression::CompressionLayer::new()); .layer(tower_http::compression::CompressionLayer::new());
@@ -127,22 +123,22 @@ async fn routing_between_services() {
use std::convert::Infallible; use std::convert::Infallible;
use tower::service_fn; use tower::service_fn;
async fn handle(_: Request<Body>) -> &'static str { async fn handle(_: Request) -> &'static str {
"handler" "handler"
} }
let app = Router::new() let app = Router::new()
.route( .route(
"/one", "/one",
get_service(service_fn(|_: Request<Body>| async { get_service(service_fn(|_: Request| async {
Ok::<_, Infallible>(Response::new(Body::from("one get"))) Ok::<_, Infallible>(Response::new(Body::from("one get")))
})) }))
.post_service(service_fn(|_: Request<Body>| async { .post_service(service_fn(|_: Request| async {
Ok::<_, Infallible>(Response::new(Body::from("one post"))) Ok::<_, Infallible>(Response::new(Body::from("one post")))
})) }))
.on_service( .on_service(
MethodFilter::PUT, MethodFilter::PUT,
service_fn(|_: Request<Body>| async { service_fn(|_: Request| async {
Ok::<_, Infallible>(Response::new(Body::from("one put"))) Ok::<_, Infallible>(Response::new(Body::from("one put")))
}), }),
), ),
@@ -173,7 +169,7 @@ async fn middleware_on_single_route() {
use tower::ServiceBuilder; use tower::ServiceBuilder;
use tower_http::{compression::CompressionLayer, trace::TraceLayer}; use tower_http::{compression::CompressionLayer, trace::TraceLayer};
async fn handle(_: Request<Body>) -> &'static str { async fn handle(_: Request) -> &'static str {
"Hello, World!" "Hello, World!"
} }
@@ -197,7 +193,7 @@ async fn middleware_on_single_route() {
#[crate::test] #[crate::test]
async fn service_in_bottom() { async fn service_in_bottom() {
async fn handler(_req: Request<Body>) -> Result<Response<Body>, Infallible> { async fn handler(_req: Request) -> Result<Response<Body>, Infallible> {
Ok(Response::new(Body::empty())) Ok(Response::new(Body::empty()))
} }
@@ -235,7 +231,7 @@ async fn wrong_method_service() {
struct Svc; struct Svc;
impl<R> Service<R> for Svc { impl<R> Service<R> for Svc {
type Response = Response<Empty<Bytes>>; type Response = Response;
type Error = Infallible; type Error = Infallible;
type Future = Ready<Result<Self::Response, Self::Error>>; type Future = Ready<Result<Self::Response, Self::Error>>;
@@ -244,7 +240,7 @@ async fn wrong_method_service() {
} }
fn call(&mut self, _req: R) -> Self::Future { fn call(&mut self, _req: R) -> Self::Future {
ready(Ok(Response::new(Empty::new()))) ready(Ok(().into_response()))
} }
} }
@@ -271,7 +267,7 @@ async fn wrong_method_service() {
#[crate::test] #[crate::test]
async fn multiple_methods_for_one_handler() { async fn multiple_methods_for_one_handler() {
async fn root(_: Request<Body>) -> &'static str { async fn root(_: Request) -> &'static str {
"Hello, World!" "Hello, World!"
} }
+4 -4
View File
@@ -1,5 +1,5 @@
use super::*; use super::*;
use crate::{body::boxed, extract::Extension}; use crate::extract::Extension;
use std::collections::HashMap; use std::collections::HashMap;
use tower_http::services::ServeDir; use tower_http::services::ServeDir;
@@ -141,7 +141,7 @@ async fn nested_url_extractor() {
.route("/baz", get(|uri: Uri| async move { uri.to_string() })) .route("/baz", get(|uri: Uri| async move { uri.to_string() }))
.route( .route(
"/qux", "/qux",
get(|req: Request<Body>| async move { req.uri().to_string() }), get(|req: Request| async move { req.uri().to_string() }),
), ),
), ),
); );
@@ -185,8 +185,8 @@ async fn nested_service_sees_stripped_uri() {
"/bar", "/bar",
Router::new().route_service( Router::new().route_service(
"/baz", "/baz",
service_fn(|req: Request<Body>| async move { service_fn(|req: Request| async move {
let body = boxed(Body::from(req.uri().to_string())); let body = Body::from(req.uri().to_string());
Ok::<_, Infallible>(Response::new(body)) Ok::<_, Infallible>(Response::new(body))
}), }),
), ),
+5 -2
View File
@@ -4,7 +4,7 @@ use http::{
header::{HeaderName, HeaderValue}, header::{HeaderName, HeaderValue},
Request, StatusCode, Request, StatusCode,
}; };
use hyper::{Body, Server}; use hyper::Server;
use std::net::{SocketAddr, TcpListener}; use std::net::{SocketAddr, TcpListener};
use tower::make::Shared; use tower::make::Shared;
use tower_service::Service; use tower_service::Service;
@@ -17,7 +17,10 @@ pub(crate) struct TestClient {
impl TestClient { impl TestClient {
pub(crate) fn new<S, ResBody>(svc: S) -> Self pub(crate) fn new<S, ResBody>(svc: S) -> Self
where where
S: Service<Request<Body>, Response = http::Response<ResBody>> + Clone + Send + 'static, S: Service<Request<hyper::Body>, Response = http::Response<ResBody>>
+ Clone
+ Send
+ 'static,
ResBody: HttpBody + Send + 'static, ResBody: HttpBody + Send + 'static,
ResBody::Data: Send, ResBody::Data: Send,
ResBody::Error: Into<BoxError>, ResBody::Error: Into<BoxError>,
@@ -7,8 +7,8 @@
use axum::{ use axum::{
async_trait, async_trait,
body::{Body, Bytes}, body::{Body, Bytes},
extract::FromRequest, extract::{FromRequest, Request},
http::{Request, StatusCode}, http::StatusCode,
middleware::{self, Next}, middleware::{self, Next},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::post, routing::post,
@@ -41,10 +41,7 @@ async fn main() {
} }
// middleware that shows how to consume the request body upfront // middleware that shows how to consume the request body upfront
async fn print_request_body( async fn print_request_body(request: Request, next: Next) -> Result<impl IntoResponse, Response> {
request: Request<Body>,
next: Next<Body>,
) -> Result<impl IntoResponse, Response> {
let request = buffer_request_body(request).await?; let request = buffer_request_body(request).await?;
Ok(next.run(request).await) Ok(next.run(request).await)
@@ -52,7 +49,7 @@ async fn print_request_body(
// the trick is to take the request apart, buffer the body, do what you need to do, then put // the trick is to take the request apart, buffer the body, do what you need to do, then put
// the request back together // the request back together
async fn buffer_request_body(request: Request<Body>) -> Result<Request<Body>, Response> { async fn buffer_request_body(request: Request) -> Result<Request, Response> {
let (parts, body) = request.into_parts(); let (parts, body) = request.into_parts();
// this wont work if the body is an long running stream // this wont work if the body is an long running stream
@@ -84,7 +81,7 @@ where
{ {
type Rejection = Response; type Rejection = Response;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let body = Bytes::from_request(req, state) let body = Bytes::from_request(req, state)
.await .await
.map_err(|err| err.into_response())?; .map_err(|err| err.into_response())?;
@@ -6,9 +6,7 @@
//! - Complexity: Manually implementing `FromRequest` results on more complex code //! - Complexity: Manually implementing `FromRequest` results on more complex code
use axum::{ use axum::{
async_trait, async_trait,
body::Body, extract::{rejection::JsonRejection, FromRequest, MatchedPath, Request},
extract::{rejection::JsonRejection, FromRequest, MatchedPath},
http::Request,
http::StatusCode, http::StatusCode,
response::IntoResponse, response::IntoResponse,
RequestPartsExt, RequestPartsExt,
@@ -30,7 +28,7 @@ where
{ {
type Rejection = (StatusCode, axum::Json<Value>); type Rejection = (StatusCode, axum::Json<Value>);
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let (mut parts, body) = req.into_parts(); let (mut parts, body) = req.into_parts();
// We can use other extractors to provide better rejection messages. // We can use other extractors to provide better rejection messages.
+5 -4
View File
@@ -13,8 +13,9 @@
//! Example is based on <https://github.com/hyperium/hyper/blob/master/examples/http_proxy.rs> //! Example is based on <https://github.com/hyperium/hyper/blob/master/examples/http_proxy.rs>
use axum::{ use axum::{
body::{self, Body}, body::Body,
http::{Method, Request, StatusCode}, extract::Request,
http::{Method, StatusCode},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::get, routing::get,
Router, Router,
@@ -59,7 +60,7 @@ async fn main() {
.unwrap(); .unwrap();
} }
async fn proxy(req: Request<Body>) -> Result<Response, hyper::Error> { async fn proxy(req: Request) -> Result<Response, hyper::Error> {
tracing::trace!(?req); tracing::trace!(?req);
if let Some(host_addr) = req.uri().authority().map(|auth| auth.to_string()) { if let Some(host_addr) = req.uri().authority().map(|auth| auth.to_string()) {
@@ -74,7 +75,7 @@ async fn proxy(req: Request<Body>) -> Result<Response, hyper::Error> {
} }
}); });
Ok(Response::new(body::boxed(body::Empty::new()))) Ok(Response::new(Body::empty()))
} else { } else {
tracing::warn!("CONNECT host is not socket addr: {:?}", req.uri()); tracing::warn!("CONNECT host is not socket addr: {:?}", req.uri());
Ok(( Ok((
+2 -2
View File
@@ -4,7 +4,7 @@
//! cargo run -p example-low-level-rustls //! cargo run -p example-low-level-rustls
//! ``` //! ```
use axum::{body::Body, extract::ConnectInfo, http::Request, routing::get, Router}; use axum::{extract::ConnectInfo, extract::Request, routing::get, Router};
use futures_util::future::poll_fn; use futures_util::future::poll_fn;
use hyper::server::{ use hyper::server::{
accept::Accept, accept::Accept,
@@ -67,7 +67,7 @@ async fn main() {
let protocol = protocol.clone(); let protocol = protocol.clone();
let svc = MakeService::<_, Request<Body>>::make_service(&mut app, &stream); let svc = MakeService::<_, Request<hyper::Body>>::make_service(&mut app, &stream);
tokio::spawn(async move { tokio::spawn(async move {
if let Ok(stream) = acceptor.accept(stream).await { if let Ok(stream) = acceptor.accept(stream).await {
@@ -8,9 +8,8 @@
use axum::{ use axum::{
async_trait, async_trait,
body::Body, extract::{FromRequest, Request},
extract::FromRequest, http::{header::CONTENT_TYPE, StatusCode},
http::{header::CONTENT_TYPE, Request, StatusCode},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::post, routing::post,
Form, Json, RequestExt, Router, Form, Json, RequestExt, Router,
@@ -61,7 +60,7 @@ where
{ {
type Rejection = Response; type Rejection = Response;
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Rejection> {
let content_type_header = req.headers().get(CONTENT_TYPE); let content_type_header = req.headers().get(CONTENT_TYPE);
let content_type = content_type_header.and_then(|value| value.to_str().ok()); let content_type = content_type_header.and_then(|value| value.to_str().ok());
+4 -3
View File
@@ -6,7 +6,8 @@
use axum::{ use axum::{
body::{Body, Bytes}, body::{Body, Bytes},
http::{Request, StatusCode}, extract::Request,
http::StatusCode,
middleware::{self, Next}, middleware::{self, Next},
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::post, routing::post,
@@ -38,8 +39,8 @@ async fn main() {
} }
async fn print_request_response( async fn print_request_response(
req: Request<Body>, req: Request,
next: Next<Body>, next: Next,
) -> Result<impl IntoResponse, (StatusCode, String)> { ) -> Result<impl IntoResponse, (StatusCode, String)> {
let (parts, body) = req.into_parts(); let (parts, body) = req.into_parts();
let bytes = buffer_and_print("request", body).await?; let bytes = buffer_and_print("request", body).await?;
+2 -3
View File
@@ -8,8 +8,7 @@
//! ``` //! ```
use axum::{ use axum::{
extract::MatchedPath, extract::{MatchedPath, Request},
http::Request,
middleware::{self, Next}, middleware::{self, Next},
response::IntoResponse, response::IntoResponse,
routing::get, routing::get,
@@ -94,7 +93,7 @@ fn setup_metrics_recorder() -> PrometheusHandle {
.unwrap() .unwrap()
} }
async fn track_metrics<B>(req: Request<B>, next: Next<B>) -> impl IntoResponse { async fn track_metrics(req: Request, next: Next) -> impl IntoResponse {
let start = Instant::now(); let start = Instant::now();
let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() { let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() {
matched_path.as_str().to_owned() matched_path.as_str().to_owned()
@@ -1,6 +1,10 @@
use axum::{body::BoxBody, http::header::CONTENT_TYPE, response::IntoResponse}; use axum::{
body::Body,
extract::Request,
http::header::CONTENT_TYPE,
response::{IntoResponse, Response},
};
use futures::{future::BoxFuture, ready}; use futures::{future::BoxFuture, ready};
use hyper::{Body, Request, Response};
use std::{ use std::{
convert::Infallible, convert::Infallible,
task::{Context, Poll}, task::{Context, Poll},
@@ -41,16 +45,16 @@ where
} }
} }
impl<A, B> Service<Request<Body>> for MultiplexService<A, B> impl<A, B> Service<Request<hyper::Body>> for MultiplexService<A, B>
where where
A: Service<Request<Body>, Error = Infallible>, A: Service<Request<hyper::Body>, Error = Infallible>,
A::Response: IntoResponse, A::Response: IntoResponse,
A::Future: Send + 'static, A::Future: Send + 'static,
B: Service<Request<Body>, Error = Infallible>, B: Service<Request<hyper::Body>, Error = Infallible>,
B::Response: IntoResponse, B::Response: IntoResponse,
B::Future: Send + 'static, B::Future: Send + 'static,
{ {
type Response = Response<BoxBody>; type Response = Response<Body>;
type Error = Infallible; type Error = Infallible;
type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>; type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
@@ -73,7 +77,7 @@ where
} }
} }
fn call(&mut self, req: Request<Body>) -> Self::Future { fn call(&mut self, req: Request<hyper::Body>) -> Self::Future {
// require users to call `poll_ready` first, if they don't we're allowed to panic // require users to call `poll_ready` first, if they don't we're allowed to panic
// as per the `tower::Service` contract // as per the `tower::Service` contract
assert!( assert!(
+3 -3
View File
@@ -9,8 +9,8 @@
use axum::{ use axum::{
body::Body, body::Body,
extract::State, extract::{Request, State},
http::{uri::Uri, Request}, http::uri::Uri,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::get, routing::get,
Router, Router,
@@ -36,7 +36,7 @@ async fn main() {
.unwrap(); .unwrap();
} }
async fn handler(State(client): State<Client>, mut req: Request<Body>) -> Response { async fn handler(State(client): State<Client>, mut req: Request) -> Response {
let path = req.uri().path(); let path = req.uri().path();
let path_query = req let path_query = req
.uri() .uri()
+2 -6
View File
@@ -5,11 +5,7 @@
//! ``` //! ```
use axum::{ use axum::{
body::Body, extract::Request, handler::HandlerWithoutStateExt, http::StatusCode, routing::get, Router,
handler::HandlerWithoutStateExt,
http::{Request, StatusCode},
routing::get,
Router,
}; };
use std::net::SocketAddr; use std::net::SocketAddr;
use tower::ServiceExt; use tower::ServiceExt;
@@ -97,7 +93,7 @@ fn calling_serve_dir_from_a_handler() -> Router {
// call `ServeDir` yourself from a handler // call `ServeDir` yourself from a handler
Router::new().nest_service( Router::new().nest_service(
"/foo", "/foo",
get(|request: Request<Body>| async { get(|request: Request| async {
let service = ServeDir::new("assets"); let service = ServeDir::new("assets");
let result = service.oneshot(request).await; let result = service.oneshot(request).await;
result result
+4 -4
View File
@@ -5,9 +5,9 @@
//! ``` //! ```
use axum::{ use axum::{
body::{Body, Bytes}, body::Bytes,
extract::{Multipart, Path}, extract::{Multipart, Path, Request},
http::{Request, StatusCode}, http::StatusCode,
response::{Html, Redirect}, response::{Html, Redirect},
routing::{get, post}, routing::{get, post},
BoxError, Router, BoxError, Router,
@@ -52,7 +52,7 @@ async fn main() {
// POST'ing to `/file/foo.txt` will create a file called `foo.txt`. // POST'ing to `/file/foo.txt` will create a file called `foo.txt`.
async fn save_request_body( async fn save_request_body(
Path(file_name): Path<String>, Path(file_name): Path<String>,
request: Request<Body>, request: Request,
) -> Result<(), (StatusCode, String)> { ) -> Result<(), (StatusCode, String)> {
stream_to_file(&file_name, request.into_body()).await stream_to_file(&file_name, request.into_body()).await
} }
+5 -10
View File
@@ -162,7 +162,7 @@ mod tests {
// in multiple request // in multiple request
#[tokio::test] #[tokio::test]
async fn multiple_request() { async fn multiple_request() {
let mut app = app(); let mut app = app().into_service();
let request = Request::builder().uri("/").body(Body::empty()).unwrap(); let request = Request::builder().uri("/").body(Body::empty()).unwrap();
let response = ServiceExt::<Request<Body>>::ready(&mut app) let response = ServiceExt::<Request<Body>>::ready(&mut app)
@@ -190,20 +190,15 @@ mod tests {
// tests. // tests.
#[tokio::test] #[tokio::test]
async fn with_into_make_service_with_connect_info() { async fn with_into_make_service_with_connect_info() {
let mut app = app().layer(MockConnectInfo(SocketAddr::from(([0, 0, 0, 0], 3000)))); let mut app = app()
.layer(MockConnectInfo(SocketAddr::from(([0, 0, 0, 0], 3000))))
.into_service();
let request = Request::builder() let request = Request::builder()
.uri("/requires-connect-into") .uri("/requires-connect-into")
.body(Body::empty()) .body(Body::empty())
.unwrap(); .unwrap();
let response = app let response = app.ready().await.unwrap().call(request).await.unwrap();
.as_service()
.ready()
.await
.unwrap()
.call(request)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK); assert_eq!(response.status(), StatusCode::OK);
} }
} }
+3 -4
View File
@@ -12,9 +12,8 @@
use async_trait::async_trait; use async_trait::async_trait;
use axum::{ use axum::{
body::Body, extract::{rejection::FormRejection, Form, FromRequest, Request},
extract::{rejection::FormRejection, Form, FromRequest}, http::StatusCode,
http::{Request, StatusCode},
response::{Html, IntoResponse, Response}, response::{Html, IntoResponse, Response},
routing::get, routing::get,
Router, Router,
@@ -70,7 +69,7 @@ where
{ {
type Rejection = ServerError; type Rejection = ServerError;
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> { async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let Form(value) = Form::<T>::from_request(req, state).await?; let Form(value) = Form::<T>::from_request(req, state).await?;
value.validate()?; value.validate()?;
Ok(ValidatedForm(value)) Ok(ValidatedForm(value))