1
0
Fork 0
mirror of https://github.com/tokio-rs/axum.git synced 2025-04-26 13:56:22 +02:00

It works?

This commit is contained in:
Jonas Platte 2022-11-05 14:36:42 +01:00
parent 7f55e3663b
commit 0a43a23c00
No known key found for this signature in database
GPG key ID: CC154DE0E30B7C67
12 changed files with 66 additions and 125 deletions

View file

@ -2,7 +2,7 @@
members = [
"axum",
"axum-core",
#"axum-extra",
"axum-extra",
"axum-macros",
]
resolver = "2"

View file

@ -17,6 +17,9 @@ mod tests {
InnerState: FromRef<OuterState>,
{
type Rejection = Infallible;
type Future<'a> = impl Future<Output = Result<Self, Self::Rejection>> + 'a
where
OuterState: 'a;
fn from_request_parts<'a>(
_parts: &'a mut Parts,
@ -37,6 +40,9 @@ mod tests {
S: Send + Sync,
String: FromRef<S>,
{
type Future<'a> = impl Future<Output = Result<Self, Self::Rejection>> + 'a
where
S: 'a;
type Rejection = Infallible;
fn from_request_parts<'a>(_parts: &'a mut Parts, state: &'a S) -> Self::Future<'a> {

View file

@ -165,7 +165,7 @@ mod tests {
async fn extract_without_state() {
let req = Request::new(());
let method: Method = req.extract().await.unwrap();
let method = req.extract::<Method, _>().await.unwrap();
assert_eq!(method, Method::GET);
}
@ -174,7 +174,7 @@ mod tests {
async fn extract_body_without_state() {
let req = Request::new(Body::from("foobar"));
let body: String = req.extract().await.unwrap();
let body = req.extract::<String, _>().await.unwrap();
assert_eq!(body, "foobar");
}
@ -185,7 +185,10 @@ mod tests {
let state = "state".to_owned();
let State(extracted_state): State<String> = req.extract_with_state(&state).await.unwrap();
let State(extracted_state) = req
.extract_with_state::<State<String>, _, _>(&state)
.await
.unwrap();
assert_eq!(extracted_state, state);
}
@ -224,16 +227,19 @@ mod tests {
impl<S, B> FromRequest<S, B> for WorksForCustomExtractor
where
S: Send + Sync,
B: Send + 'static,
String: FromRef<S> + FromRequest<(), B>,
{
type Future<'a> = impl Future<Output = Result<Self, Self::Rejection>> + 'a
where
B: 'a,
S: 'a;
type Rejection = <String as FromRequest<(), B>>::Rejection;
fn from_request(mut req: Request<B>, state: &S) -> Self::Future<'_> {
async move {
let RequiresState(from_state) = req.extract_parts_with_state(state).await.unwrap();
let method = req.extract_parts().await.unwrap();
let body = req.extract().await?;
let body = req.extract::<String, _>().await?;
Ok(Self {
method,

View file

@ -54,7 +54,7 @@ mod tests {
async fn extract_without_state() {
let (mut parts, _) = Request::new(()).into_parts();
let method: Method = parts.extract().await.unwrap();
let method = parts.extract::<Method>().await.unwrap();
assert_eq!(method, Method::GET);
}
@ -85,15 +85,16 @@ mod tests {
S: Send + Sync,
String: FromRef<S>,
{
type Future<'a> = impl Future<Output = Result<Self, Self::Rejection>> + 'a
where
S: 'a;
type Rejection = Infallible;
fn from_request_parts<'a>(
parts: &'a mut Parts,
state: &'a S,
) -> impl Future<Output = Result<Self, Self::Rejection>> + 'a {
fn from_request_parts<'a>(parts: &'a mut Parts, state: &'a S) -> Self::Future<'a> {
async move {
let RequiresState(from_state) = parts.extract_with_state(state).await?;
let method = parts.extract().await?;
let RequiresState(from_state) =
parts.extract_with_state::<RequiresState, _>(state).await?;
let method = parts.extract::<Method>().await?;
Ok(Self { method, from_state })
}

View file

@ -138,6 +138,7 @@ pub struct BodyStream<B>(SyncWrapper<BodyStreamInner<B>>)
where
B: HttpBody;
#[allow(type_alias_bounds)]
type BodyStreamInner<B: HttpBody> = http_body::combinators::MapErr<
http_body::combinators::MapData<B, fn(B::Data) -> Bytes>,
fn(B::Error) -> Error,

View file

@ -2,7 +2,6 @@ use crate::{
extract::FromRequestParts,
response::{IntoResponse, Response},
};
use futures_util::{future::BoxFuture, ready};
use http::Request;
use pin_project_lite::pin_project;
use std::{
@ -10,7 +9,7 @@ use std::{
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
task::{ready, Context, Poll},
};
use tower_layer::Layer;
use tower_service::Service;
@ -206,7 +205,8 @@ where
{
type Response = Response;
type Error = T::Error;
type Future = ResponseFuture<B, T, E, S>;
type Future =
ResponseFuture<B, T, E, S, impl Future<Output = (Request<B>, Result<E, E::Rejection>)>>;
#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
@ -215,16 +215,17 @@ where
fn call(&mut self, req: Request<B>) -> Self::Future {
let state = self.state.clone();
let extract_future = Box::pin(async move {
let future = async move {
let (mut parts, body) = req.into_parts();
let extracted = E::from_request_parts(&mut parts, &state).await;
let req = Request::from_parts(parts, body);
(req, extracted)
});
};
ResponseFuture {
state: State::Extracting {
future: extract_future,
future,
_phantom: PhantomData,
},
svc: Some(self.inner.clone()),
}
@ -234,36 +235,40 @@ where
pin_project! {
/// Response future for [`FromExtractor`].
#[allow(missing_debug_implementations)]
pub struct ResponseFuture<B, T, E, S>
pub struct ResponseFuture<B, T, E, S, F>
where
E: FromRequestParts<S>,
T: Service<Request<B>>,
F: Future<Output = (Request<B>, Result<E, E::Rejection>)>,
{
#[pin]
state: State<B, T, E, S>,
state: State<B, T, E, S, F>,
svc: Option<T>,
}
}
pin_project! {
#[project = StateProj]
enum State<B, T, E, S>
enum State<B, T, E, S, F>
where
E: FromRequestParts<S>,
T: Service<Request<B>>,
F: Future<Output = (Request<B>, Result<E, E::Rejection>)>,
{
Extracting {
future: BoxFuture<'static, (Request<B>, Result<E, E::Rejection>)>,
#[pin] future: F,
_phantom: PhantomData<fn() -> S>
},
Call { #[pin] future: T::Future },
}
}
impl<B, T, E, S> Future for ResponseFuture<B, T, E, S>
impl<B, T, E, S, F> Future for ResponseFuture<B, T, E, S, F>
where
E: FromRequestParts<S>,
T: Service<Request<B>>,
T::Response: IntoResponse,
F: Future<Output = (Request<B>, Result<E, E::Rejection>)>,
{
type Output = Result<Response, T::Error>;
@ -272,7 +277,7 @@ where
let mut this = self.as_mut().project();
let new_state = match this.state.as_mut().project() {
StateProj::Extracting { future } => {
StateProj::Extracting { mut future, .. } => {
let (req, extracted) = ready!(future.as_mut().poll(cx));
match extracted {

View file

@ -1,6 +1,5 @@
use crate::response::{IntoResponse, Response};
use axum_core::extract::{FromRequest, FromRequestParts};
use futures_util::future::BoxFuture;
use http::Request;
use std::{
any::type_name,
@ -8,7 +7,6 @@ use std::{
fmt,
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use tower::{util::BoxCloneService, ServiceBuilder};
@ -250,7 +248,7 @@ macro_rules! impl_service {
{
type Response = Response;
type Error = Infallible;
type Future = ResponseFuture;
type Future = impl Future<Output = Result<Response, Infallible>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
@ -263,13 +261,13 @@ macro_rules! impl_service {
let mut f = self.f.clone();
let state = self.state.clone();
let future = Box::pin(async move {
async move {
let (mut parts, body) = req.into_parts();
$(
let $ty = match $ty::from_request_parts(&mut parts, &state).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response(),
Err(rejection) => return Ok(rejection.into_response()),
};
)*
@ -277,7 +275,7 @@ macro_rules! impl_service {
let $last = match $last::from_request(req, &state).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response(),
Err(rejection) => return Ok(rejection.into_response()),
};
let inner = ServiceBuilder::new()
@ -286,11 +284,7 @@ macro_rules! impl_service {
.service(ready_inner);
let next = Next { inner };
f($($ty,)* $last, next).await.into_response()
});
ResponseFuture {
inner: future
Ok(f($($ty,)* $last, next).await.into_response())
}
}
}
@ -336,25 +330,6 @@ impl<B> fmt::Debug for Next<B> {
}
}
/// Response future for [`FromFn`].
pub struct ResponseFuture {
inner: BoxFuture<'static, Response>,
}
impl Future for ResponseFuture {
type Output = Result<Response, Infallible>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.inner.as_mut().poll(cx).map(Ok)
}
}
impl fmt::Debug for ResponseFuture {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ResponseFuture").finish()
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -1,6 +1,5 @@
use crate::response::{IntoResponse, Response};
use axum_core::extract::{FromRequest, FromRequestParts};
use futures_util::future::BoxFuture;
use http::Request;
use std::{
any::type_name,
@ -8,7 +7,6 @@ use std::{
fmt,
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use tower_layer::Layer;
@ -263,7 +261,7 @@ macro_rules! impl_service {
{
type Response = Response;
type Error = Infallible;
type Future = ResponseFuture;
type Future = impl Future<Output = Result<Response, Infallible>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
@ -276,13 +274,13 @@ macro_rules! impl_service {
let mut f = self.f.clone();
let state = self.state.clone();
let future = Box::pin(async move {
async move {
let (mut parts, body) = req.into_parts();
$(
let $ty = match $ty::from_request_parts(&mut parts, &state).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response(),
Err(rejection) => return Ok(rejection.into_response()),
};
)*
@ -290,21 +288,17 @@ macro_rules! impl_service {
let $last = match $last::from_request(req, &state).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response(),
Err(rejection) => return Ok(rejection.into_response()),
};
match f($($ty,)* $last).await.into_map_request_result() {
Ok(req) => {
ready_inner.call(req).await.into_response()
Ok(ready_inner.call(req).await.into_response())
}
Err(res) => {
res
Ok(res)
}
}
});
ResponseFuture {
inner: future
}
}
}
@ -327,25 +321,6 @@ where
}
}
/// Response future for [`MapRequest`].
pub struct ResponseFuture {
inner: BoxFuture<'static, Response>,
}
impl Future for ResponseFuture {
type Output = Result<Response, Infallible>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.inner.as_mut().poll(cx).map(Ok)
}
}
impl fmt::Debug for ResponseFuture {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ResponseFuture").finish()
}
}
mod private {
use crate::{http::Request, response::IntoResponse};

View file

@ -1,6 +1,5 @@
use crate::response::{IntoResponse, Response};
use axum_core::extract::FromRequestParts;
use futures_util::future::BoxFuture;
use http::Request;
use std::{
any::type_name,
@ -8,7 +7,6 @@ use std::{
fmt,
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use tower_layer::Layer;
@ -246,13 +244,12 @@ macro_rules! impl_service {
{
type Response = Response;
type Error = Infallible;
type Future = ResponseFuture;
type Future = impl Future<Output = Result<Response, Infallible>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, req: Request<B>) -> Self::Future {
let not_ready_inner = self.inner.clone();
let mut ready_inner = std::mem::replace(&mut self.inner, not_ready_inner);
@ -260,13 +257,13 @@ macro_rules! impl_service {
let mut f = self.f.clone();
let _state = self.state.clone();
let future = Box::pin(async move {
async move {
let (mut parts, body) = req.into_parts();
$(
let $ty = match $ty::from_request_parts(&mut parts, &_state).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response(),
Err(rejection) => return Ok(rejection.into_response()),
};
)*
@ -274,14 +271,10 @@ macro_rules! impl_service {
match ready_inner.call(req).await {
Ok(res) => {
f($($ty,)* res).await.into_response()
Ok(f($($ty,)* res).await.into_response())
}
Err(err) => match err {}
}
});
ResponseFuture {
inner: future
}
}
}
@ -320,25 +313,6 @@ where
}
}
/// Response future for [`MapResponse`].
pub struct ResponseFuture {
inner: BoxFuture<'static, Response>,
}
impl Future for ResponseFuture {
type Output = Result<Response, Infallible>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.inner.as_mut().poll(cx).map(Ok)
}
}
impl fmt::Debug for ResponseFuture {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ResponseFuture").finish()
}
}
#[cfg(test)]
mod tests {
#[allow(unused_imports)]

View file

@ -18,12 +18,3 @@ pub use self::map_response::{
map_response, map_response_with_state, MapResponse, MapResponseLayer,
};
pub use crate::extension::AddExtension;
pub mod future {
//! Future types.
pub use super::from_extractor::ResponseFuture as FromExtractorResponseFuture;
pub use super::from_fn::ResponseFuture as FromFnResponseFuture;
pub use super::map_request::ResponseFuture as MapRequestResponseFuture;
pub use super::map_response::ResponseFuture as MapResponseResponseFuture;
}

View file

@ -143,6 +143,7 @@ macro_rules! top_level_handler_fn {
pub fn $name<H, T, S, B>(handler: H) -> MethodRouter<S, B, Infallible>
where
H: Handler<T, S, B>,
H::Future: Send,
B: Send + 'static,
T: 'static,
S: Clone + Send + Sync + 'static,
@ -280,6 +281,7 @@ macro_rules! chained_handler_fn {
pub fn $name<H, T>(self, handler: H) -> Self
where
H: Handler<T, S, B>,
H::Future: Send,
T: 'static,
S: Send + Sync + 'static,
{
@ -430,6 +432,7 @@ top_level_handler_fn!(trace, TRACE);
pub fn on<H, T, S, B>(filter: MethodFilter, handler: H) -> MethodRouter<S, B, Infallible>
where
H: Handler<T, S, B>,
H::Future: Send,
B: Send + 'static,
T: 'static,
S: Clone + Send + Sync + 'static,
@ -477,6 +480,7 @@ where
pub fn any<H, T, S, B>(handler: H) -> MethodRouter<S, B, Infallible>
where
H: Handler<T, S, B>,
H::Future: Send,
B: Send + 'static,
T: 'static,
S: Clone + Send + Sync + 'static,
@ -601,6 +605,7 @@ where
pub fn on<H, T>(self, filter: MethodFilter, handler: H) -> Self
where
H: Handler<T, S, B>,
H::Future: Send,
T: 'static,
S: Send + Sync + 'static,
{
@ -623,6 +628,7 @@ where
pub fn fallback<H, T>(mut self, handler: H) -> Self
where
H: Handler<T, S, B>,
H::Future: Send,
T: 'static,
S: Send + Sync + 'static,
{

View file

@ -488,6 +488,7 @@ where
pub fn fallback<H, T>(mut self, handler: H) -> Self
where
H: Handler<T, S, B>,
H::Future: Send,
T: 'static,
{
self.fallback = Fallback::BoxedHandler(BoxedHandler::new(handler));