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:
parent
7f55e3663b
commit
0a43a23c00
12 changed files with 66 additions and 125 deletions
|
@ -2,7 +2,7 @@
|
|||
members = [
|
||||
"axum",
|
||||
"axum-core",
|
||||
#"axum-extra",
|
||||
"axum-extra",
|
||||
"axum-macros",
|
||||
]
|
||||
resolver = "2"
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Reference in a new issue