mirror of
https://github.com/tokio-rs/axum.git
synced 2025-10-02 07:20:38 +00:00
Move response futures into their own modules (#130)
It cleans up the docs to have the futures in their own modules as users are unlikely to look at them. Also matches the pattern used in tower https://docs.rs/tower/0.4.8/tower/util/future/index.html. Added re-exports to the old locations so its not a breaking change.
This commit is contained in:
parent
68f826ef3b
commit
d4ce90e2e6
@ -163,7 +163,7 @@ where
|
|||||||
{
|
{
|
||||||
type Response = Response<BoxBody>;
|
type Response = Response<BoxBody>;
|
||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = ExtractorMiddlewareResponseFuture<ReqBody, S, E>;
|
type Future = ResponseFuture<ReqBody, S, E>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
@ -177,7 +177,7 @@ where
|
|||||||
(req, extracted)
|
(req, extracted)
|
||||||
});
|
});
|
||||||
|
|
||||||
ExtractorMiddlewareResponseFuture {
|
ResponseFuture {
|
||||||
state: State::Extracting {
|
state: State::Extracting {
|
||||||
future: extract_future,
|
future: extract_future,
|
||||||
},
|
},
|
||||||
@ -186,10 +186,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.1.3",
|
||||||
|
note = "Use axum::extract::extractor_middleware::ResponseFuture"
|
||||||
|
)]
|
||||||
|
pub type ExtractorMiddlewareResponseFuture<B, S, E> = ResponseFuture<B, S, E>;
|
||||||
|
|
||||||
pin_project! {
|
pin_project! {
|
||||||
/// Response future for [`ExtractorMiddleware`].
|
/// Response future for [`ExtractorMiddleware`].
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct ExtractorMiddlewareResponseFuture<ReqBody, S, E>
|
pub struct ResponseFuture<ReqBody, S, E>
|
||||||
where
|
where
|
||||||
E: FromRequest<ReqBody>,
|
E: FromRequest<ReqBody>,
|
||||||
S: Service<Request<ReqBody>>,
|
S: Service<Request<ReqBody>>,
|
||||||
@ -212,7 +219,7 @@ pin_project! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ReqBody, S, E, ResBody> Future for ExtractorMiddlewareResponseFuture<ReqBody, S, E>
|
impl<ReqBody, S, E, ResBody> Future for ResponseFuture<ReqBody, S, E>
|
||||||
where
|
where
|
||||||
E: FromRequest<ReqBody>,
|
E: FromRequest<ReqBody>,
|
||||||
S: Service<Request<ReqBody>, Response = Response<ResBody>>,
|
S: Service<Request<ReqBody>, Response = Response<ResBody>>,
|
||||||
|
108
src/routing.rs
108
src/routing.rs
@ -9,26 +9,29 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::future;
|
|
||||||
use http::{Method, Request, Response, StatusCode, Uri};
|
use http::{Method, Request, Response, StatusCode, Uri};
|
||||||
use pin_project_lite::pin_project;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt,
|
fmt,
|
||||||
future::Future,
|
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
pin::Pin,
|
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
use tower::{
|
use tower::{
|
||||||
util::{BoxService, Oneshot, ServiceExt},
|
util::{BoxService, ServiceExt},
|
||||||
BoxError, Layer, Service, ServiceBuilder,
|
BoxError, Layer, Service, ServiceBuilder,
|
||||||
};
|
};
|
||||||
use tower_http::map_response_body::MapResponseBodyLayer;
|
use tower_http::map_response_body::MapResponseBodyLayer;
|
||||||
|
|
||||||
|
pub mod future;
|
||||||
|
|
||||||
|
// for backwards compatibility
|
||||||
|
// TODO: remove these in 0.2
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use self::future::{BoxRouteFuture, EmptyRouterFuture, RouteFuture};
|
||||||
|
|
||||||
/// A filter that matches one or more HTTP methods.
|
/// A filter that matches one or more HTTP methods.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum MethodFilter {
|
pub enum MethodFilter {
|
||||||
@ -385,63 +388,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_project! {
|
|
||||||
/// The response future for [`Route`].
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct RouteFuture<S, F, B>
|
|
||||||
where
|
|
||||||
S: Service<Request<B>>,
|
|
||||||
F: Service<Request<B>> {
|
|
||||||
#[pin] inner: RouteFutureInner<S, F, B>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, F, B> RouteFuture<S, F, B>
|
|
||||||
where
|
|
||||||
S: Service<Request<B>>,
|
|
||||||
F: Service<Request<B>>,
|
|
||||||
{
|
|
||||||
pub(crate) fn a(a: Oneshot<S, Request<B>>) -> Self {
|
|
||||||
RouteFuture {
|
|
||||||
inner: RouteFutureInner::A { a },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn b(b: Oneshot<F, Request<B>>) -> Self {
|
|
||||||
RouteFuture {
|
|
||||||
inner: RouteFutureInner::B { b },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pin_project! {
|
|
||||||
#[project = RouteFutureInnerProj]
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum RouteFutureInner<S, F, B>
|
|
||||||
where
|
|
||||||
S: Service<Request<B>>,
|
|
||||||
F: Service<Request<B>>,
|
|
||||||
{
|
|
||||||
A { #[pin] a: Oneshot<S, Request<B>> },
|
|
||||||
B { #[pin] b: Oneshot<F, Request<B>> },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S, F, B> Future for RouteFuture<S, F, B>
|
|
||||||
where
|
|
||||||
S: Service<Request<B>, Response = Response<BoxBody>>,
|
|
||||||
F: Service<Request<B>, Response = Response<BoxBody>, Error = S::Error>,
|
|
||||||
{
|
|
||||||
type Output = Result<Response<BoxBody>, S::Error>;
|
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
match self.project().inner.project() {
|
|
||||||
RouteFutureInnerProj::A { a } => a.poll(cx),
|
|
||||||
RouteFutureInnerProj::B { b } => b.poll(cx),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct UrlParams(pub(crate) Vec<(ByteStr, ByteStr)>);
|
pub(crate) struct UrlParams(pub(crate) Vec<(ByteStr, ByteStr)>);
|
||||||
|
|
||||||
@ -520,17 +466,11 @@ impl<B, E> Service<Request<B>> for EmptyRouter<E> {
|
|||||||
let mut res = Response::new(crate::body::empty());
|
let mut res = Response::new(crate::body::empty());
|
||||||
*res.status_mut() = self.status;
|
*res.status_mut() = self.status;
|
||||||
EmptyRouterFuture {
|
EmptyRouterFuture {
|
||||||
future: future::ok(res),
|
future: futures_util::future::ok(res),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opaque_future! {
|
|
||||||
/// Response future for [`EmptyRouter`].
|
|
||||||
pub type EmptyRouterFuture<E> =
|
|
||||||
future::Ready<Result<Response<BoxBody>, E>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct PathPattern(Arc<Inner>);
|
pub(crate) struct PathPattern(Arc<Inner>);
|
||||||
|
|
||||||
@ -666,36 +606,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin_project! {
|
|
||||||
/// The response future for [`BoxRoute`].
|
|
||||||
pub struct BoxRouteFuture<B, E>
|
|
||||||
where
|
|
||||||
E: Into<BoxError>,
|
|
||||||
{
|
|
||||||
#[pin] inner: Oneshot<MpscBuffer<BoxService<Request<B>, Response<BoxBody>, E>, Request<B>>, Request<B>>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B, E> Future for BoxRouteFuture<B, E>
|
|
||||||
where
|
|
||||||
E: Into<BoxError>,
|
|
||||||
{
|
|
||||||
type Output = Result<Response<BoxBody>, E>;
|
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
self.project().inner.poll(cx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B, E> fmt::Debug for BoxRouteFuture<B, E>
|
|
||||||
where
|
|
||||||
E: Into<BoxError>,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.debug_struct("BoxRouteFuture").finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A [`Service`] created from a router by applying a Tower middleware.
|
/// A [`Service`] created from a router by applying a Tower middleware.
|
||||||
///
|
///
|
||||||
/// Created with [`RoutingDsl::layer`]. See that method for more details.
|
/// Created with [`RoutingDsl::layer`]. See that method for more details.
|
||||||
|
117
src/routing/future.rs
Normal file
117
src/routing/future.rs
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
//! Future types.
|
||||||
|
|
||||||
|
use crate::{body::BoxBody, buffer::MpscBuffer};
|
||||||
|
use http::{Request, Response};
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use std::{
|
||||||
|
fmt,
|
||||||
|
future::Future,
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
use tower::{
|
||||||
|
util::{BoxService, Oneshot},
|
||||||
|
BoxError, Service,
|
||||||
|
};
|
||||||
|
|
||||||
|
opaque_future! {
|
||||||
|
/// Response future for [`EmptyRouter`](super::EmptyRouter).
|
||||||
|
pub type EmptyRouterFuture<E> =
|
||||||
|
futures_util::future::Ready<Result<Response<BoxBody>, E>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// The response future for [`BoxRoute`](super::BoxRoute).
|
||||||
|
pub struct BoxRouteFuture<B, E>
|
||||||
|
where
|
||||||
|
E: Into<BoxError>,
|
||||||
|
{
|
||||||
|
#[pin]
|
||||||
|
pub(super) inner: Oneshot<
|
||||||
|
MpscBuffer<
|
||||||
|
BoxService<Request<B>, Response<BoxBody>, E >,
|
||||||
|
Request<B>
|
||||||
|
>,
|
||||||
|
Request<B>,
|
||||||
|
>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E> Future for BoxRouteFuture<B, E>
|
||||||
|
where
|
||||||
|
E: Into<BoxError>,
|
||||||
|
{
|
||||||
|
type Output = Result<Response<BoxBody>, E>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
self.project().inner.poll(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<B, E> fmt::Debug for BoxRouteFuture<B, E>
|
||||||
|
where
|
||||||
|
E: Into<BoxError>,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("BoxRouteFuture").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// The response future for [`Route`](super::Route).
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RouteFuture<S, F, B>
|
||||||
|
where
|
||||||
|
S: Service<Request<B>>,
|
||||||
|
F: Service<Request<B>>
|
||||||
|
{
|
||||||
|
#[pin]
|
||||||
|
inner: RouteFutureInner<S, F, B>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, F, B> RouteFuture<S, F, B>
|
||||||
|
where
|
||||||
|
S: Service<Request<B>>,
|
||||||
|
F: Service<Request<B>>,
|
||||||
|
{
|
||||||
|
pub(crate) fn a(a: Oneshot<S, Request<B>>) -> Self {
|
||||||
|
RouteFuture {
|
||||||
|
inner: RouteFutureInner::A { a },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn b(b: Oneshot<F, Request<B>>) -> Self {
|
||||||
|
RouteFuture {
|
||||||
|
inner: RouteFutureInner::B { b },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
#[project = RouteFutureInnerProj]
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum RouteFutureInner<S, F, B>
|
||||||
|
where
|
||||||
|
S: Service<Request<B>>,
|
||||||
|
F: Service<Request<B>>,
|
||||||
|
{
|
||||||
|
A { #[pin] a: Oneshot<S, Request<B>> },
|
||||||
|
B { #[pin] b: Oneshot<F, Request<B>> },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S, F, B> Future for RouteFuture<S, F, B>
|
||||||
|
where
|
||||||
|
S: Service<Request<B>, Response = Response<BoxBody>>,
|
||||||
|
F: Service<Request<B>, Response = Response<BoxBody>, Error = S::Error>,
|
||||||
|
{
|
||||||
|
type Output = Result<Response<BoxBody>, S::Error>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
match self.project().inner.project() {
|
||||||
|
RouteFutureInnerProj::A { a } => a.poll(cx),
|
||||||
|
RouteFutureInnerProj::B { b } => b.poll(cx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -50,3 +50,27 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// Response future for [`BoxResponseBody`].
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BoxResponseBodyFuture<F> {
|
||||||
|
#[pin]
|
||||||
|
pub(super) future: F,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, B, E> Future for BoxResponseBodyFuture<F>
|
||||||
|
where
|
||||||
|
F: Future<Output = Result<Response<B>, E>>,
|
||||||
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
type Output = Result<Response<BoxBody>, E>;
|
||||||
|
|
||||||
|
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let res = ready!(self.project().future.poll(cx))?;
|
||||||
|
let res = res.map(box_body);
|
||||||
|
Poll::Ready(Ok(res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -87,18 +87,15 @@
|
|||||||
//! [load shed]: tower::load_shed
|
//! [load shed]: tower::load_shed
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
body::{box_body, BoxBody},
|
body::BoxBody,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
routing::{EmptyRouter, MethodFilter, RouteFuture},
|
routing::{EmptyRouter, MethodFilter, RouteFuture},
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::ready;
|
|
||||||
use http::{Request, Response};
|
use http::{Request, Response};
|
||||||
use pin_project_lite::pin_project;
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt,
|
fmt,
|
||||||
future::Future,
|
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
@ -106,6 +103,10 @@ use tower::{util::Oneshot, BoxError, Service, ServiceExt as _};
|
|||||||
|
|
||||||
pub mod future;
|
pub mod future;
|
||||||
|
|
||||||
|
// for backwards compatibility
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use future::BoxResponseBodyFuture;
|
||||||
|
|
||||||
/// Route requests to the given service regardless of the HTTP method.
|
/// Route requests to the given service regardless of the HTTP method.
|
||||||
///
|
///
|
||||||
/// See [`get`] for an example.
|
/// See [`get`] for an example.
|
||||||
@ -637,7 +638,7 @@ where
|
|||||||
{
|
{
|
||||||
type Response = Response<BoxBody>;
|
type Response = Response<BoxBody>;
|
||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = BoxResponseBodyFuture<Oneshot<S, Request<ReqBody>>>;
|
type Future = future::BoxResponseBodyFuture<Oneshot<S, Request<ReqBody>>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
@ -645,29 +646,6 @@ where
|
|||||||
|
|
||||||
fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
|
fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
|
||||||
let fut = self.inner.clone().oneshot(req);
|
let fut = self.inner.clone().oneshot(req);
|
||||||
BoxResponseBodyFuture { future: fut }
|
future::BoxResponseBodyFuture { future: fut }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pin_project! {
|
|
||||||
/// Response future for [`BoxResponseBody`].
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct BoxResponseBodyFuture<F> {
|
|
||||||
#[pin] future: F,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F, B, E> Future for BoxResponseBodyFuture<F>
|
|
||||||
where
|
|
||||||
F: Future<Output = Result<Response<B>, E>>,
|
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
type Output = Result<Response<BoxBody>, E>;
|
|
||||||
|
|
||||||
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
let res = ready!(self.project().future.poll(cx))?;
|
|
||||||
let res = res.map(box_body);
|
|
||||||
Poll::Ready(Ok(res))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user