Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove B type param #1751

Merged
merged 26 commits into from
Mar 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4596c3c
Start working on v0.7.0
davidpdrsn Nov 25, 2022
8685796
Add `axum_core::body::Body` (#1584)
davidpdrsn Nov 27, 2022
97d3258
FromRequest
davidpdrsn Feb 12, 2023
b7f0dcd
Handler
davidpdrsn Feb 12, 2023
3b64f85
Router
davidpdrsn Feb 12, 2023
beeb567
MethodRouter
davidpdrsn Feb 12, 2023
a95da74
Remove `B` type param: axum-core (#1772)
davidpdrsn Feb 20, 2023
dea73f8
Remove `B` type param: axum-extra (#1775)
davidpdrsn Feb 21, 2023
69e8b04
Remove `B` type param: `Router`, `MethodRouter`, `Handler` (#1774)
davidpdrsn Feb 21, 2023
92722fc
Remove `B` type param: rest of axum (#1776)
davidpdrsn Feb 21, 2023
412f388
Start working on v0.7.0
davidpdrsn Nov 25, 2022
d9de5ec
Add `axum_core::body::Body` (#1584)
davidpdrsn Nov 27, 2022
d81effb
Change `sse::Event::json_data` to use `axum_core::Error` as its error…
davidpdrsn Feb 16, 2023
813dbac
Fix typo in extract::ws (#1664)
mscofield0 Feb 24, 2023
b9e0c0c
Remove `B` type param: the rest (#1778)
davidpdrsn Feb 28, 2023
161bb60
Merge branch 'v0.7.0' into remove-generic-b-type-prep
davidpdrsn Mar 1, 2023
d039c35
Add workaround for inference errors after removing `B` type param (#1…
davidpdrsn Mar 12, 2023
02eb3a6
Merge branch 'v0.7.0' into remove-generic-b-type-prep
davidpdrsn Mar 12, 2023
dd0d5e5
Merge remote-tracking branch 'origin/remove-generic-b-type-prep' into…
davidpdrsn Mar 12, 2023
4eb9bf6
try again
davidpdrsn Mar 12, 2023
2de724e
Add `Router::into_service`
davidpdrsn Mar 12, 2023
d8a504c
changelog
davidpdrsn Mar 12, 2023
8496c85
format
davidpdrsn Mar 12, 2023
ee7f6ef
fix ui tests
davidpdrsn Mar 12, 2023
72f90b4
spa.rs committed by accident
davidpdrsn Mar 12, 2023
9b69d39
changelog
davidpdrsn Mar 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 45 additions & 44 deletions axum-core/src/ext_traits/request.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::body::Body;
use crate::extract::{DefaultBodyLimitKind, FromRequest, FromRequestParts};
use futures_util::future::BoxFuture;
use http::Request;
use http_body::Limited;

mod sealed {
pub trait Sealed<B> {}
impl<B> Sealed<B> for http::Request<B> {}
pub trait Sealed {}
impl Sealed for http::Request<crate::body::Body> {}
}

/// Extension trait that adds additional methods to [`Request`].
pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
pub trait RequestExt: sealed::Sealed + Sized {
/// Apply an extractor to this `Request`.
///
/// This is just a convenience for `E::from_request(req, &())`.
Expand All @@ -23,6 +24,7 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// use axum::{
/// async_trait,
/// extract::FromRequest,
/// body::Body,
/// http::{header::CONTENT_TYPE, Request, StatusCode},
/// response::{IntoResponse, Response},
/// Form, Json, RequestExt,
Expand All @@ -31,17 +33,16 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// struct FormOrJson<T>(T);
///
/// #[async_trait]
/// impl<S, B, T> FromRequest<S, B> for FormOrJson<T>
/// impl<S, T> FromRequest<S> for FormOrJson<T>
/// where
/// Json<T>: FromRequest<(), B>,
/// Form<T>: FromRequest<(), B>,
/// Json<T>: FromRequest<()>,
/// Form<T>: FromRequest<()>,
/// T: 'static,
/// B: Send + 'static,
/// S: Send + Sync,
/// {
/// type Rejection = Response;
///
/// async fn from_request(req: Request<B>, _state: &S) -> Result<Self, Self::Rejection> {
/// async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
/// let content_type = req
/// .headers()
/// .get(CONTENT_TYPE)
Expand Down Expand Up @@ -70,7 +71,7 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// ```
fn extract<E, M>(self) -> BoxFuture<'static, Result<E, E::Rejection>>
where
E: FromRequest<(), B, M> + 'static,
E: FromRequest<(), M> + 'static,
M: 'static;

/// Apply an extractor that requires some state to this `Request`.
Expand All @@ -85,6 +86,7 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// ```
/// use axum::{
/// async_trait,
/// body::Body,
/// extract::{FromRef, FromRequest},
/// http::Request,
/// RequestExt,
Expand All @@ -95,15 +97,14 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// }
///
/// #[async_trait]
/// impl<S, B> FromRequest<S, B> for MyExtractor
/// impl<S> FromRequest<S> for MyExtractor
/// where
/// String: FromRef<S>,
/// S: Send + Sync,
/// B: Send + 'static,
/// {
/// type Rejection = std::convert::Infallible;
///
/// async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
/// async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
/// let requires_state = req.extract_with_state::<RequiresState, _, _>(state).await?;
///
/// Ok(Self { requires_state })
Expand All @@ -114,22 +115,21 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// struct RequiresState { /* ... */ }
///
/// #[async_trait]
/// impl<S, B> FromRequest<S, B> for RequiresState
/// impl<S> FromRequest<S> for RequiresState
/// where
/// String: FromRef<S>,
/// S: Send + Sync,
/// B: Send + 'static,
/// {
/// // ...
/// # type Rejection = std::convert::Infallible;
/// # async fn from_request(req: Request<B>, _state: &S) -> Result<Self, Self::Rejection> {
/// # async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
/// # todo!()
/// # }
/// }
/// ```
fn extract_with_state<E, S, M>(self, state: &S) -> BoxFuture<'_, Result<E, E::Rejection>>
where
E: FromRequest<S, B, M> + 'static,
E: FromRequest<S, M> + 'static,
S: Send + Sync;

/// Apply a parts extractor to this `Request`.
Expand All @@ -145,6 +145,7 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// headers::{authorization::Bearer, Authorization},
/// http::Request,
/// response::{IntoResponse, Response},
/// body::Body,
/// Json, RequestExt, TypedHeader,
/// };
///
Expand All @@ -154,16 +155,15 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// }
///
/// #[async_trait]
/// impl<S, B, T> FromRequest<S, B> for MyExtractor<T>
/// impl<S, T> FromRequest<S> for MyExtractor<T>
/// where
/// B: Send + 'static,
/// S: Send + Sync,
/// Json<T>: FromRequest<(), B>,
/// Json<T>: FromRequest<()>,
/// T: 'static,
/// {
/// type Rejection = Response;
///
/// async fn from_request(mut req: Request<B>, _state: &S) -> Result<Self, Self::Rejection> {
/// async fn from_request(mut req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
/// let TypedHeader(auth_header) = req
/// .extract_parts::<TypedHeader<Authorization<Bearer>>>()
/// .await
Expand Down Expand Up @@ -197,6 +197,7 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// extract::{FromRef, FromRequest, FromRequestParts},
/// http::{request::Parts, Request},
/// response::{IntoResponse, Response},
/// body::Body,
/// Json, RequestExt,
/// };
///
Expand All @@ -206,17 +207,16 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// }
///
/// #[async_trait]
/// impl<S, B, T> FromRequest<S, B> for MyExtractor<T>
/// impl<S, T> FromRequest<S> for MyExtractor<T>
/// where
/// String: FromRef<S>,
/// Json<T>: FromRequest<(), B>,
/// Json<T>: FromRequest<()>,
/// T: 'static,
/// S: Send + Sync,
/// B: Send + 'static,
/// {
/// type Rejection = Response;
///
/// async fn from_request(mut req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
/// async fn from_request(mut req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
/// let requires_state = req
/// .extract_parts_with_state::<RequiresState, _>(state)
/// .await
Expand Down Expand Up @@ -260,29 +260,26 @@ pub trait RequestExt<B>: sealed::Sealed<B> + Sized {
/// Apply the [default body limit](crate::extract::DefaultBodyLimit).
///
/// If it is disabled, return the request as-is in `Err`.
fn with_limited_body(self) -> Result<Request<Limited<B>>, Request<B>>;
fn with_limited_body(self) -> Result<Request<Limited<Body>>, Request<Body>>;

/// 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 is disabled.
fn into_limited_body(self) -> Result<Limited<B>, B>;
fn into_limited_body(self) -> Result<Limited<Body>, Body>;
}

impl<B> RequestExt<B> for Request<B>
where
B: Send + 'static,
{
impl RequestExt for Request<Body> {
fn extract<E, M>(self) -> BoxFuture<'static, Result<E, E::Rejection>>
where
E: FromRequest<(), B, M> + 'static,
E: FromRequest<(), M> + 'static,
M: 'static,
{
self.extract_with_state(&())
}

fn extract_with_state<E, S, M>(self, state: &S) -> BoxFuture<'_, Result<E, E::Rejection>>
where
E: FromRequest<S, B, M> + 'static,
E: FromRequest<S, M> + 'static,
S: Send + Sync,
{
E::from_request(self, state)
Expand Down Expand Up @@ -324,7 +321,7 @@ where
})
}

fn with_limited_body(self) -> Result<Request<Limited<B>>, Request<B>> {
fn with_limited_body(self) -> Result<Request<Limited<Body>>, Request<Body>> {
// update docs in `axum-core/src/extract/default_body_limit.rs` and
// `axum/src/docs/extract.md` if this changes
const DEFAULT_LIMIT: usize = 2_097_152; // 2 mb
Expand All @@ -338,7 +335,7 @@ where
}
}

fn into_limited_body(self) -> Result<Limited<B>, B> {
fn into_limited_body(self) -> Result<Limited<Body>, Body> {
self.with_limited_body()
.map(Request::into_body)
.map_err(Request::into_body)
Expand All @@ -354,11 +351,10 @@ mod tests {
};
use async_trait::async_trait;
use http::Method;
use hyper::Body;

#[tokio::test]
async fn extract_without_state() {
let req = Request::new(());
let req = Request::new(Body::empty());

let method: Method = req.extract().await.unwrap();

Expand All @@ -376,7 +372,7 @@ mod tests {

#[tokio::test]
async fn extract_with_state() {
let req = Request::new(());
let req = Request::new(Body::empty());

let state = "state".to_owned();

Expand All @@ -387,7 +383,10 @@ mod tests {

#[tokio::test]
async fn extract_parts_without_state() {
let mut req = Request::builder().header("x-foo", "foo").body(()).unwrap();
let mut req = Request::builder()
.header("x-foo", "foo")
.body(Body::empty())
.unwrap();

let method: Method = req.extract_parts().await.unwrap();

Expand All @@ -397,7 +396,10 @@ mod tests {

#[tokio::test]
async fn extract_parts_with_state() {
let mut req = Request::builder().header("x-foo", "foo").body(()).unwrap();
let mut req = Request::builder()
.header("x-foo", "foo")
.body(Body::empty())
.unwrap();

let state = "state".to_owned();

Expand All @@ -417,15 +419,14 @@ mod tests {
}

#[async_trait]
impl<S, B> FromRequest<S, B> for WorksForCustomExtractor
impl<S> FromRequest<S> for WorksForCustomExtractor
where
S: Send + Sync,
B: Send + 'static,
String: FromRef<S> + FromRequest<(), B>,
String: FromRef<S> + FromRequest<()>,
{
type Rejection = <String as FromRequest<(), B>>::Rejection;
type Rejection = <String as FromRequest<()>>::Rejection;

async fn from_request(mut req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
async fn from_request(mut req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
let RequiresState(from_state) = req.extract_parts_with_state(state).await.unwrap();
let method = req.extract_parts().await.unwrap();
let body = req.extract().await?;
Expand Down
10 changes: 5 additions & 5 deletions axum-core/src/extract/default_body_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use tower_layer::Layer;
/// post(|request: Request<Body>| async {}),
/// )
/// .layer(DefaultBodyLimit::max(1024));
/// # let _: Router<(), _> = app;
/// # let _: Router = app;
/// ```
///
/// ```
Expand All @@ -54,10 +54,10 @@ use tower_layer::Layer;
/// "/",
/// // `RequestBodyLimitLayer` changes the request body type to `Limited<Body>`
/// // extracting a different body type wont work
/// post(|request: Request<Limited<Body>>| async {}),
/// post(|request: Request<Body>| async {}),
/// )
/// .layer(RequestBodyLimitLayer::new(1024));
/// # let _: Router<(), _> = app;
/// # let _: Router = app;
/// ```
///
/// In general using `DefaultBodyLimit` is recommended but if you need to use third party
Expand Down Expand Up @@ -105,7 +105,7 @@ impl DefaultBodyLimit {
/// use tower_http::limit::RequestBodyLimitLayer;
/// use http_body::Limited;
///
/// let app: Router<(), Limited<Body>> = Router::new()
/// let app: Router<()> = Router::new()
/// .route("/", get(|body: Bytes| async {}))
/// // Disable the default limit
/// .layer(DefaultBodyLimit::disable())
Expand Down Expand Up @@ -141,7 +141,7 @@ impl DefaultBodyLimit {
/// use tower_http::limit::RequestBodyLimitLayer;
/// use http_body::Limited;
///
/// let app: Router<(), Limited<Body>> = Router::new()
/// let app: Router<()> = Router::new()
/// .route("/", get(|body: Bytes| async {}))
/// // Replace the default of 2MB with 1024 bytes.
/// .layer(DefaultBodyLimit::max(1024));
Expand Down
Loading