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: axum-extra #1775

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions axum-extra/src/extract/cookie/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ mod tests {
custom_key: CustomKey(Key::generate()),
};

let app = Router::<_, Body>::new()
let app = Router::new()
.route("/set", get(set_cookie))
.route("/get", get(get_cookie))
.route("/remove", get(remove_cookie))
Expand Down Expand Up @@ -352,7 +352,7 @@ mod tests {
custom_key: CustomKey(Key::generate()),
};

let app = Router::<_, Body>::new()
let app = Router::new()
.route("/get", get(get_cookie))
.with_state(state);

Expand Down
11 changes: 4 additions & 7 deletions axum-extra/src/extract/form.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use axum::{
async_trait,
body::HttpBody,
body::Body,
extract::{rejection::RawFormRejection, FromRequest, RawForm},
response::{IntoResponse, Response},
BoxError, Error, RequestExt,
Error, RequestExt,
};
use http::{Request, StatusCode};
use serde::de::DeserializeOwned;
Expand Down Expand Up @@ -52,17 +52,14 @@ impl<T> Deref for Form<T> {
}

#[async_trait]
impl<T, S, B> FromRequest<S, B> for Form<T>
impl<T, S> FromRequest<S> for Form<T>
where
T: DeserializeOwned,
B: HttpBody + Send + 'static,
B::Data: Send,
B::Error: Into<BoxError>,
S: Send + Sync,
{
type Rejection = FormRejection;

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 RawForm(bytes) = req
.extract()
.await
Expand Down
10 changes: 5 additions & 5 deletions axum-extra/src/extract/with_rejection.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use axum::async_trait;
use axum::body::Body;
use axum::extract::{FromRequest, FromRequestParts};
use axum::response::IntoResponse;
use http::request::Parts;
Expand Down Expand Up @@ -109,16 +110,15 @@ impl<E, R> DerefMut for WithRejection<E, R> {
}

#[async_trait]
impl<B, E, R, S> FromRequest<S, B> for WithRejection<E, R>
impl<E, R, S> FromRequest<S> for WithRejection<E, R>
where
B: Send + 'static,
S: Send + Sync,
E: FromRequest<S, B>,
E: FromRequest<S>,
R: From<E::Rejection> + IntoResponse,
{
type Rejection = R;

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 extractor = E::from_request(req, state).await?;
Ok(WithRejection(extractor, PhantomData))
}
Expand Down Expand Up @@ -180,7 +180,7 @@ mod tests {
}
}

let req = Request::new(());
let req = Request::new(Body::empty());
let result = WithRejection::<TestExtractor, TestRejection>::from_request(req, &()).await;
assert!(matches!(result, Err(TestRejection)));

Expand Down
33 changes: 17 additions & 16 deletions axum-extra/src/handler/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Additional handler utilities.

use axum::body::Body;
use axum::{
extract::FromRequest,
handler::Handler,
Expand All @@ -19,15 +20,15 @@ pub use self::or::Or;
///
/// The drawbacks of this trait is that you cannot apply middleware to individual handlers like you
/// can with [`Handler::layer`].
pub trait HandlerCallWithExtractors<T, S, B>: Sized {
pub trait HandlerCallWithExtractors<T, S>: Sized {
/// The type of future calling this handler returns.
type Future: Future<Output = Response> + Send + 'static;

/// Call the handler with the extracted inputs.
fn call(self, extractors: T, state: S) -> <Self as HandlerCallWithExtractors<T, S, B>>::Future;
fn call(self, extractors: T, state: S) -> <Self as HandlerCallWithExtractors<T, S>>::Future;

/// Conver this `HandlerCallWithExtractors` into [`Handler`].
fn into_handler(self) -> IntoHandler<Self, T, S, B> {
fn into_handler(self) -> IntoHandler<Self, T, S> {
IntoHandler {
handler: self,
_marker: PhantomData,
Expand Down Expand Up @@ -102,9 +103,9 @@ pub trait HandlerCallWithExtractors<T, S, B>: Sized {
/// );
/// # let _: Router = app;
/// ```
fn or<R, Rt>(self, rhs: R) -> Or<Self, R, T, Rt, S, B>
fn or<R, Rt>(self, rhs: R) -> Or<Self, R, T, Rt, S>
where
R: HandlerCallWithExtractors<Rt, S, B>,
R: HandlerCallWithExtractors<Rt, S>,
{
Or {
lhs: self,
Expand All @@ -117,7 +118,7 @@ pub trait HandlerCallWithExtractors<T, S, B>: Sized {
macro_rules! impl_handler_call_with {
( $($ty:ident),* $(,)? ) => {
#[allow(non_snake_case)]
impl<F, Fut, S, B, $($ty,)*> HandlerCallWithExtractors<($($ty,)*), S, B> for F
impl<F, Fut, S, $($ty,)*> HandlerCallWithExtractors<($($ty,)*), S> for F
where
F: FnOnce($($ty,)*) -> Fut,
Fut: Future + Send + 'static,
Expand All @@ -130,7 +131,7 @@ macro_rules! impl_handler_call_with {
self,
($($ty,)*): ($($ty,)*),
_state: S,
) -> <Self as HandlerCallWithExtractors<($($ty,)*), S, B>>::Future {
) -> <Self as HandlerCallWithExtractors<($($ty,)*), S>>::Future {
self($($ty,)*).map(IntoResponse::into_response)
}
}
Expand Down Expand Up @@ -159,22 +160,22 @@ impl_handler_call_with!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
///
/// Created with [`HandlerCallWithExtractors::into_handler`].
#[allow(missing_debug_implementations)]
pub struct IntoHandler<H, T, S, B> {
pub struct IntoHandler<H, T, S> {
handler: H,
_marker: PhantomData<fn() -> (T, S, B)>,
_marker: PhantomData<fn() -> (T, S)>,
}

impl<H, T, S, B> Handler<T, S, B> for IntoHandler<H, T, S, B>
impl<H, T, S> Handler<T, S> for IntoHandler<H, T, S>
where
H: HandlerCallWithExtractors<T, S, B> + Clone + Send + 'static,
T: FromRequest<S, B> + Send + 'static,
H: HandlerCallWithExtractors<T, S> + Clone + Send + 'static,
T: FromRequest<S> + Send + 'static,
T::Rejection: Send,
B: Send + 'static,
S: Send + Sync + 'static,
{
type Future = BoxFuture<'static, Response>;

fn call(self, req: http::Request<B>, state: S) -> Self::Future {
fn call(self, req: http::Request<Body>, state: S) -> Self::Future {
let req = req.map(Body::new);
Box::pin(async move {
match T::from_request(req, &state).await {
Ok(t) => self.handler.call(t, state).await,
Expand All @@ -184,9 +185,9 @@ where
}
}

impl<H, T, S, B> Copy for IntoHandler<H, T, S, B> where H: Copy {}
impl<H, T, S> Copy for IntoHandler<H, T, S> where H: Copy {}

impl<H, T, S, B> Clone for IntoHandler<H, T, S, B>
impl<H, T, S> Clone for IntoHandler<H, T, S>
where
H: Clone,
{
Expand Down
29 changes: 14 additions & 15 deletions axum-extra/src/handler/or.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::HandlerCallWithExtractors;
use crate::either::Either;
use axum::{
body::Body,
extract::{FromRequest, FromRequestParts},
handler::Handler,
http::Request,
Expand All @@ -14,19 +15,18 @@ use std::{future::Future, marker::PhantomData};
///
/// Created with [`HandlerCallWithExtractors::or`](super::HandlerCallWithExtractors::or).
#[allow(missing_debug_implementations)]
pub struct Or<L, R, Lt, Rt, S, B> {
pub struct Or<L, R, Lt, Rt, S> {
pub(super) lhs: L,
pub(super) rhs: R,
pub(super) _marker: PhantomData<fn() -> (Lt, Rt, S, B)>,
pub(super) _marker: PhantomData<fn() -> (Lt, Rt, S)>,
}

impl<S, B, L, R, Lt, Rt> HandlerCallWithExtractors<Either<Lt, Rt>, S, B> for Or<L, R, Lt, Rt, S, B>
impl<S, L, R, Lt, Rt> HandlerCallWithExtractors<Either<Lt, Rt>, S> for Or<L, R, Lt, Rt, S>
where
L: HandlerCallWithExtractors<Lt, S, B> + Send + 'static,
R: HandlerCallWithExtractors<Rt, S, B> + Send + 'static,
L: HandlerCallWithExtractors<Lt, S> + Send + 'static,
R: HandlerCallWithExtractors<Rt, S> + Send + 'static,
Rt: Send + 'static,
Lt: Send + 'static,
B: Send + 'static,
{
// this puts `futures_util` in our public API but thats fine in axum-extra
type Future = EitherFuture<
Expand All @@ -38,7 +38,7 @@ where
self,
extractors: Either<Lt, Rt>,
state: S,
) -> <Self as HandlerCallWithExtractors<Either<Lt, Rt>, S, B>>::Future {
) -> <Self as HandlerCallWithExtractors<Either<Lt, Rt>, S>>::Future {
match extractors {
Either::E1(lt) => self
.lhs
Expand All @@ -54,21 +54,20 @@ where
}
}

impl<S, B, L, R, Lt, Rt, M> Handler<(M, Lt, Rt), S, B> for Or<L, R, Lt, Rt, S, B>
impl<S, L, R, Lt, Rt, M> Handler<(M, Lt, Rt), S> for Or<L, R, Lt, Rt, S>
where
L: HandlerCallWithExtractors<Lt, S, B> + Clone + Send + 'static,
R: HandlerCallWithExtractors<Rt, S, B> + Clone + Send + 'static,
L: HandlerCallWithExtractors<Lt, S> + Clone + Send + 'static,
R: HandlerCallWithExtractors<Rt, S> + Clone + Send + 'static,
Lt: FromRequestParts<S> + Send + 'static,
Rt: FromRequest<S, B, M> + Send + 'static,
Rt: FromRequest<S, M> + Send + 'static,
Lt::Rejection: Send,
Rt::Rejection: Send,
B: Send + 'static,
S: Send + Sync + 'static,
{
// this puts `futures_util` in our public API but thats fine in axum-extra
type Future = BoxFuture<'static, Response>;

fn call(self, req: Request<B>, state: S) -> Self::Future {
fn call(self, req: Request<Body>, state: S) -> Self::Future {
Box::pin(async move {
let (mut parts, body) = req.into_parts();

Expand All @@ -86,14 +85,14 @@ where
}
}

impl<L, R, Lt, Rt, S, B> Copy for Or<L, R, Lt, Rt, S, B>
impl<L, R, Lt, Rt, S> Copy for Or<L, R, Lt, Rt, S>
where
L: Copy,
R: Copy,
{
}

impl<L, R, Lt, Rt, S, B> Clone for Or<L, R, Lt, Rt, S, B>
impl<L, R, Lt, Rt, S> Clone for Or<L, R, Lt, Rt, S>
where
L: Clone,
R: Clone,
Expand Down
39 changes: 6 additions & 33 deletions axum-extra/src/json_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

use axum::{
async_trait,
body::{HttpBody, StreamBody},
body::{Body, StreamBody},
extract::FromRequest,
response::{IntoResponse, Response},
BoxError,
};
use bytes::{BufMut, Bytes, BytesMut};
use bytes::{BufMut, BytesMut};
use futures_util::stream::{BoxStream, Stream, TryStream, TryStreamExt};
use http::Request;
use pin_project_lite::pin_project;
Expand Down Expand Up @@ -100,26 +100,19 @@ impl<S> JsonLines<S, AsResponse> {
}

#[async_trait]
impl<S, B, T> FromRequest<S, B> for JsonLines<T, AsExtractor>
impl<S, T> FromRequest<S> for JsonLines<T, AsExtractor>
where
B: HttpBody + Send + 'static,
B::Data: Into<Bytes>,
B::Error: Into<BoxError>,
T: DeserializeOwned,
S: Send + Sync,
{
type Rejection = 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> {
// `Stream::lines` isn't a thing so we have to convert it into an `AsyncRead`
// so we can call `AsyncRead::lines` and then convert it back to a `Stream`
let body = BodyStream {
body: req.into_body(),
};
let body = req.into_body();

let stream = body
.map_ok(Into::into)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err));
let stream = TryStreamExt::map_err(body, |err| io::Error::new(io::ErrorKind::Other, err));
let read = StreamReader::new(stream);
let lines_stream = LinesStream::new(read.lines());

Expand All @@ -139,26 +132,6 @@ where
}
}

// like `axum::extract::BodyStream` except it doesn't box the inner body
// we don't need that since we box the final stream in `Inner::Extractor`
pin_project! {
struct BodyStream<B> {
#[pin]
body: B,
}
}

impl<B> Stream for BodyStream<B>
where
B: HttpBody + Send + 'static,
{
type Item = Result<B::Data, B::Error>;

fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.project().body.poll_data(cx)
}
}

impl<T> Stream for JsonLines<T, AsExtractor> {
type Item = Result<T, axum::Error>;

Expand Down
12 changes: 4 additions & 8 deletions axum-extra/src/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

use axum::{
async_trait,
body::{Bytes, HttpBody},
body::Body,
extract::{rejection::BytesRejection, FromRequest},
response::{IntoResponse, Response},
BoxError,
};
use bytes::BytesMut;
use bytes::{Bytes, BytesMut};
use http::{Request, StatusCode};
use prost::Message;
use std::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -97,17 +96,14 @@ use std::ops::{Deref, DerefMut};
pub struct ProtoBuf<T>(pub T);

#[async_trait]
impl<T, S, B> FromRequest<S, B> for ProtoBuf<T>
impl<T, S> FromRequest<S> for ProtoBuf<T>
where
T: Message + Default,
B: HttpBody + Send + 'static,
B::Data: Send,
B::Error: Into<BoxError>,
S: Send + Sync,
{
type Rejection = ProtoBufRejection;

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 mut bytes = Bytes::from_request(req, state).await?;

match T::decode(&mut bytes) {
Expand Down
Loading