mirror of
https://github.com/tokio-rs/axum.git
synced 2024-12-29 15:49:16 +01:00
Remove some needless type params
This commit is contained in:
parent
696fce7b76
commit
7620f17edc
8 changed files with 132 additions and 139 deletions
|
@ -3,8 +3,8 @@ use async_trait::async_trait;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http::{header, Request, Response};
|
use http::{header, Request, Response};
|
||||||
use rejection::{
|
use rejection::{
|
||||||
BodyAlreadyTaken, FailedToBufferBody, InvalidJsonBody, InvalidUtf8, LengthRequired,
|
BodyAlreadyTaken, FailedToBufferBody, InvalidJsonBody, InvalidUrlParam, InvalidUtf8,
|
||||||
MissingExtension, MissingJsonContentType, MissingRouteParams, PayloadTooLarge,
|
LengthRequired, MissingExtension, MissingJsonContentType, MissingRouteParams, PayloadTooLarge,
|
||||||
QueryStringMissing,
|
QueryStringMissing,
|
||||||
};
|
};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
@ -13,16 +13,16 @@ use std::{collections::HashMap, convert::Infallible, str::FromStr};
|
||||||
pub mod rejection;
|
pub mod rejection;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait FromRequest<B>: Sized {
|
pub trait FromRequest: Sized {
|
||||||
type Rejection: IntoResponse<B>;
|
type Rejection: IntoResponse;
|
||||||
|
|
||||||
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection>;
|
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T, B> FromRequest<B> for Option<T>
|
impl<T> FromRequest for Option<T>
|
||||||
where
|
where
|
||||||
T: FromRequest<B>,
|
T: FromRequest,
|
||||||
{
|
{
|
||||||
type Rejection = Infallible;
|
type Rejection = Infallible;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ where
|
||||||
pub struct Query<T>(pub T);
|
pub struct Query<T>(pub T);
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T> FromRequest<Body> for Query<T>
|
impl<T> FromRequest for Query<T>
|
||||||
where
|
where
|
||||||
T: DeserializeOwned,
|
T: DeserializeOwned,
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ where
|
||||||
pub struct Json<T>(pub T);
|
pub struct Json<T>(pub T);
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T> FromRequest<Body> for Json<T>
|
impl<T> FromRequest for Json<T>
|
||||||
where
|
where
|
||||||
T: DeserializeOwned,
|
T: DeserializeOwned,
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ fn has_content_type<B>(req: &Request<B>, expected_content_type: &str) -> bool {
|
||||||
pub struct Extension<T>(pub T);
|
pub struct Extension<T>(pub T);
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T> FromRequest<Body> for Extension<T>
|
impl<T> FromRequest for Extension<T>
|
||||||
where
|
where
|
||||||
T: Clone + Send + Sync + 'static,
|
T: Clone + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
@ -116,7 +116,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl FromRequest<Body> for Bytes {
|
impl FromRequest for Bytes {
|
||||||
type Rejection = Response<Body>;
|
type Rejection = Response<Body>;
|
||||||
|
|
||||||
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
||||||
|
@ -132,7 +132,7 @@ impl FromRequest<Body> for Bytes {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl FromRequest<Body> for String {
|
impl FromRequest for String {
|
||||||
type Rejection = Response<Body>;
|
type Rejection = Response<Body>;
|
||||||
|
|
||||||
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
||||||
|
@ -153,7 +153,7 @@ impl FromRequest<Body> for String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl FromRequest<Body> for Body {
|
impl FromRequest for Body {
|
||||||
type Rejection = BodyAlreadyTaken;
|
type Rejection = BodyAlreadyTaken;
|
||||||
|
|
||||||
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
||||||
|
@ -165,7 +165,7 @@ impl FromRequest<Body> for Body {
|
||||||
pub struct BytesMaxLength<const N: u64>(pub Bytes);
|
pub struct BytesMaxLength<const N: u64>(pub Bytes);
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<const N: u64> FromRequest<Body> for BytesMaxLength<N> {
|
impl<const N: u64> FromRequest for BytesMaxLength<N> {
|
||||||
type Rejection = Response<Body>;
|
type Rejection = Response<Body>;
|
||||||
|
|
||||||
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
||||||
|
@ -208,7 +208,7 @@ impl UrlParamsMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl FromRequest<Body> for UrlParamsMap {
|
impl FromRequest for UrlParamsMap {
|
||||||
type Rejection = MissingRouteParams;
|
type Rejection = MissingRouteParams;
|
||||||
|
|
||||||
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
|
||||||
|
@ -224,30 +224,6 @@ impl FromRequest<Body> for UrlParamsMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct InvalidUrlParam {
|
|
||||||
type_name: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InvalidUrlParam {
|
|
||||||
fn new<T>() -> Self {
|
|
||||||
InvalidUrlParam {
|
|
||||||
type_name: std::any::type_name::<T>(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoResponse<Body> for InvalidUrlParam {
|
|
||||||
fn into_response(self) -> http::Response<Body> {
|
|
||||||
let mut res = http::Response::new(Body::from(format!(
|
|
||||||
"Invalid URL param. Expected something of type `{}`",
|
|
||||||
self.type_name
|
|
||||||
)));
|
|
||||||
*res.status_mut() = http::StatusCode::BAD_REQUEST;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct UrlParams<T>(pub T);
|
pub struct UrlParams<T>(pub T);
|
||||||
|
|
||||||
macro_rules! impl_parse_url {
|
macro_rules! impl_parse_url {
|
||||||
|
@ -255,7 +231,7 @@ macro_rules! impl_parse_url {
|
||||||
|
|
||||||
( $head:ident, $($tail:ident),* $(,)? ) => {
|
( $head:ident, $($tail:ident),* $(,)? ) => {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<$head, $($tail,)*> FromRequest<Body> for UrlParams<($head, $($tail,)*)>
|
impl<$head, $($tail,)*> FromRequest for UrlParams<($head, $($tail,)*)>
|
||||||
where
|
where
|
||||||
$head: FromStr + Send,
|
$head: FromStr + Send,
|
||||||
$( $tail: FromStr + Send, )*
|
$( $tail: FromStr + Send, )*
|
||||||
|
|
|
@ -10,7 +10,7 @@ macro_rules! define_rejection {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct $name(pub(super) ());
|
pub struct $name(pub(super) ());
|
||||||
|
|
||||||
impl IntoResponse<Body> for $name {
|
impl IntoResponse for $name {
|
||||||
fn into_response(self) -> http::Response<Body> {
|
fn into_response(self) -> http::Response<Body> {
|
||||||
let mut res = http::Response::new(Body::from($body));
|
let mut res = http::Response::new(Body::from($body));
|
||||||
*res.status_mut() = http::StatusCode::$status;
|
*res.status_mut() = http::StatusCode::$status;
|
||||||
|
@ -36,7 +36,7 @@ macro_rules! define_rejection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for $name {
|
impl IntoResponse for $name {
|
||||||
fn into_response(self) -> http::Response<Body> {
|
fn into_response(self) -> http::Response<Body> {
|
||||||
let mut res =
|
let mut res =
|
||||||
http::Response::new(Body::from(format!(concat!($body, ": {}"), self.0)));
|
http::Response::new(Body::from(format!(concat!($body, ": {}"), self.0)));
|
||||||
|
@ -106,3 +106,27 @@ define_rejection! {
|
||||||
#[body = "Cannot have two request body extractors for a single handler"]
|
#[body = "Cannot have two request body extractors for a single handler"]
|
||||||
pub struct BodyAlreadyTaken(());
|
pub struct BodyAlreadyTaken(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct InvalidUrlParam {
|
||||||
|
type_name: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InvalidUrlParam {
|
||||||
|
pub(super) fn new<T>() -> Self {
|
||||||
|
InvalidUrlParam {
|
||||||
|
type_name: std::any::type_name::<T>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for InvalidUrlParam {
|
||||||
|
fn into_response(self) -> http::Response<Body> {
|
||||||
|
let mut res = http::Response::new(Body::from(format!(
|
||||||
|
"Invalid URL param. Expected something of type `{}`",
|
||||||
|
self.type_name
|
||||||
|
)));
|
||||||
|
*res.status_mut() = http::StatusCode::BAD_REQUEST;
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
107
src/handler.rs
107
src/handler.rs
|
@ -17,23 +17,23 @@ use std::{
|
||||||
};
|
};
|
||||||
use tower::{util::Oneshot, BoxError, Layer, Service, ServiceExt};
|
use tower::{util::Oneshot, BoxError, Layer, Service, ServiceExt};
|
||||||
|
|
||||||
pub fn get<H, B, T>(handler: H) -> OnMethod<IntoService<H, B, T>, EmptyRouter>
|
pub fn get<H, T>(handler: H) -> OnMethod<IntoService<H, T>, EmptyRouter>
|
||||||
where
|
where
|
||||||
H: Handler<B, T>,
|
H: Handler<T>,
|
||||||
{
|
{
|
||||||
on(MethodFilter::Get, handler)
|
on(MethodFilter::Get, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post<H, B, T>(handler: H) -> OnMethod<IntoService<H, B, T>, EmptyRouter>
|
pub fn post<H, T>(handler: H) -> OnMethod<IntoService<H, T>, EmptyRouter>
|
||||||
where
|
where
|
||||||
H: Handler<B, T>,
|
H: Handler<T>,
|
||||||
{
|
{
|
||||||
on(MethodFilter::Post, handler)
|
on(MethodFilter::Post, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on<H, B, T>(method: MethodFilter, handler: H) -> OnMethod<IntoService<H, B, T>, EmptyRouter>
|
pub fn on<H, T>(method: MethodFilter, handler: H) -> OnMethod<IntoService<H, T>, EmptyRouter>
|
||||||
where
|
where
|
||||||
H: Handler<B, T>,
|
H: Handler<T>,
|
||||||
{
|
{
|
||||||
OnMethod {
|
OnMethod {
|
||||||
method,
|
method,
|
||||||
|
@ -51,41 +51,37 @@ mod sealed {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Handler<B, In>: Sized {
|
pub trait Handler<In>: Sized {
|
||||||
type Response: IntoResponse<B>;
|
|
||||||
|
|
||||||
// This seals the trait. We cannot use the regular "sealed super trait" approach
|
// This seals the trait. We cannot use the regular "sealed super trait" approach
|
||||||
// due to coherence.
|
// due to coherence.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
type Sealed: sealed::HiddentTrait;
|
type Sealed: sealed::HiddentTrait;
|
||||||
|
|
||||||
async fn call(self, req: Request<Body>) -> Response<B>;
|
async fn call(self, req: Request<Body>) -> Response<BoxBody>;
|
||||||
|
|
||||||
fn layer<L>(self, layer: L) -> Layered<L::Service, In>
|
fn layer<L>(self, layer: L) -> Layered<L::Service, In>
|
||||||
where
|
where
|
||||||
L: Layer<IntoService<Self, B, In>>,
|
L: Layer<IntoService<Self, In>>,
|
||||||
{
|
{
|
||||||
Layered::new(layer.layer(IntoService::new(self)))
|
Layered::new(layer.layer(IntoService::new(self)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_service(self) -> IntoService<Self, B, In> {
|
fn into_service(self) -> IntoService<Self, In> {
|
||||||
IntoService::new(self)
|
IntoService::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<F, Fut, B, Res> Handler<B, ()> for F
|
impl<F, Fut, Res> Handler<()> for F
|
||||||
where
|
where
|
||||||
F: FnOnce(Request<Body>) -> Fut + Send + Sync,
|
F: FnOnce(Request<Body>) -> Fut + Send + Sync,
|
||||||
Fut: Future<Output = Res> + Send,
|
Fut: Future<Output = Res> + Send,
|
||||||
Res: IntoResponse<B>,
|
Res: IntoResponse,
|
||||||
{
|
{
|
||||||
type Response = Res;
|
|
||||||
|
|
||||||
type Sealed = sealed::Hidden;
|
type Sealed = sealed::Hidden;
|
||||||
|
|
||||||
async fn call(self, req: Request<Body>) -> Response<B> {
|
async fn call(self, req: Request<Body>) -> Response<BoxBody> {
|
||||||
self(req).await.into_response()
|
self(req).await.into_response().map(BoxBody::new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,34 +91,32 @@ macro_rules! impl_handler {
|
||||||
( $head:ident, $($tail:ident),* $(,)? ) => {
|
( $head:ident, $($tail:ident),* $(,)? ) => {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
impl<F, Fut, B, Res, $head, $($tail,)*> Handler<B, ($head, $($tail,)*)> for F
|
impl<F, Fut, Res, $head, $($tail,)*> Handler<($head, $($tail,)*)> for F
|
||||||
where
|
where
|
||||||
F: FnOnce(Request<Body>, $head, $($tail,)*) -> Fut + Send + Sync,
|
F: FnOnce(Request<Body>, $head, $($tail,)*) -> Fut + Send + Sync,
|
||||||
Fut: Future<Output = Res> + Send,
|
Fut: Future<Output = Res> + Send,
|
||||||
Res: IntoResponse<B>,
|
Res: IntoResponse,
|
||||||
$head: FromRequest<B> + Send,
|
$head: FromRequest + Send,
|
||||||
$( $tail: FromRequest<B> + Send, )*
|
$( $tail: FromRequest + Send, )*
|
||||||
{
|
{
|
||||||
type Response = Res;
|
|
||||||
|
|
||||||
type Sealed = sealed::Hidden;
|
type Sealed = sealed::Hidden;
|
||||||
|
|
||||||
async fn call(self, mut req: Request<Body>) -> Response<B> {
|
async fn call(self, mut req: Request<Body>) -> Response<BoxBody> {
|
||||||
let $head = match $head::from_request(&mut req).await {
|
let $head = match $head::from_request(&mut req).await {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(rejection) => return rejection.into_response(),
|
Err(rejection) => return rejection.into_response().map(BoxBody::new),
|
||||||
};
|
};
|
||||||
|
|
||||||
$(
|
$(
|
||||||
let $tail = match $tail::from_request(&mut req).await {
|
let $tail = match $tail::from_request(&mut req).await {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(rejection) => return rejection.into_response(),
|
Err(rejection) => return rejection.into_response().map(BoxBody::new),
|
||||||
};
|
};
|
||||||
)*
|
)*
|
||||||
|
|
||||||
let res = self(req, $head, $($tail,)*).await;
|
let res = self(req, $head, $($tail,)*).await;
|
||||||
|
|
||||||
res.into_response()
|
res.into_response().map(BoxBody::new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,27 +141,26 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<S, B, T> Handler<B, T> for Layered<S, T>
|
impl<S, T, B> Handler<T> for Layered<S, T>
|
||||||
where
|
where
|
||||||
S: Service<Request<Body>, Response = Response<B>> + Send,
|
S: Service<Request<Body>, Response = Response<B>> + Send,
|
||||||
S::Error: IntoResponse<B>,
|
// S::Response: IntoResponse,
|
||||||
S::Response: IntoResponse<B>,
|
S::Error: IntoResponse,
|
||||||
S::Future: Send,
|
S::Future: Send,
|
||||||
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
type Response = S::Response;
|
|
||||||
|
|
||||||
type Sealed = sealed::Hidden;
|
type Sealed = sealed::Hidden;
|
||||||
|
|
||||||
async fn call(self, req: Request<Body>) -> Self::Response {
|
async fn call(self, req: Request<Body>) -> Response<BoxBody> {
|
||||||
// TODO(david): add tests for nesting services
|
|
||||||
match self
|
match self
|
||||||
.svc
|
.svc
|
||||||
.oneshot(req)
|
.oneshot(req)
|
||||||
.await
|
.await
|
||||||
.map_err(IntoResponse::into_response)
|
.map_err(IntoResponse::into_response)
|
||||||
{
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res.map(BoxBody::new),
|
||||||
Err(res) => res,
|
Err(res) => res.map(BoxBody::new),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,21 +177,19 @@ impl<S, T> Layered<S, T> {
|
||||||
where
|
where
|
||||||
S: Service<Request<Body>, Response = Response<B>>,
|
S: Service<Request<Body>, Response = Response<B>>,
|
||||||
F: FnOnce(S::Error) -> Res,
|
F: FnOnce(S::Error) -> Res,
|
||||||
Res: IntoResponse<B>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
let svc = HandleError::new(self.svc, f);
|
let svc = HandleError::new(self.svc, f);
|
||||||
Layered::new(svc)
|
Layered::new(svc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IntoService<H, B, T> {
|
pub struct IntoService<H, T> {
|
||||||
handler: H,
|
handler: H,
|
||||||
_marker: PhantomData<fn() -> (B, T)>,
|
_marker: PhantomData<fn() -> T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, B, T> IntoService<H, B, T> {
|
impl<H, T> IntoService<H, T> {
|
||||||
fn new(handler: H) -> Self {
|
fn new(handler: H) -> Self {
|
||||||
Self {
|
Self {
|
||||||
handler,
|
handler,
|
||||||
|
@ -207,7 +198,7 @@ impl<H, B, T> IntoService<H, B, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, B, T> Clone for IntoService<H, B, T>
|
impl<H, T> Clone for IntoService<H, T>
|
||||||
where
|
where
|
||||||
H: Clone,
|
H: Clone,
|
||||||
{
|
{
|
||||||
|
@ -219,12 +210,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H, B, T> Service<Request<Body>> for IntoService<H, B, T>
|
impl<H, T> Service<Request<Body>> for IntoService<H, T>
|
||||||
where
|
where
|
||||||
H: Handler<B, T> + Clone + Send + 'static,
|
H: Handler<T> + Clone + Send + 'static,
|
||||||
H::Response: 'static,
|
|
||||||
{
|
{
|
||||||
type Response = Response<B>;
|
type Response = Response<BoxBody>;
|
||||||
type Error = Infallible;
|
type Error = Infallible;
|
||||||
type Future = future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
type Future = future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
@ -237,7 +227,10 @@ where
|
||||||
|
|
||||||
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||||
let handler = self.handler.clone();
|
let handler = self.handler.clone();
|
||||||
Box::pin(async move { Ok(Handler::call(handler, req).await) })
|
Box::pin(async move {
|
||||||
|
let res = Handler::call(handler, req).await;
|
||||||
|
Ok(res)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,27 +242,23 @@ pub struct OnMethod<S, F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, F> OnMethod<S, F> {
|
impl<S, F> OnMethod<S, F> {
|
||||||
pub fn get<H, B, T>(self, handler: H) -> OnMethod<IntoService<H, B, T>, Self>
|
pub fn get<H, T>(self, handler: H) -> OnMethod<IntoService<H, T>, Self>
|
||||||
where
|
where
|
||||||
H: Handler<B, T>,
|
H: Handler<T>,
|
||||||
{
|
{
|
||||||
self.on(MethodFilter::Get, handler)
|
self.on(MethodFilter::Get, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post<H, B, T>(self, handler: H) -> OnMethod<IntoService<H, B, T>, Self>
|
pub fn post<H, T>(self, handler: H) -> OnMethod<IntoService<H, T>, Self>
|
||||||
where
|
where
|
||||||
H: Handler<B, T>,
|
H: Handler<T>,
|
||||||
{
|
{
|
||||||
self.on(MethodFilter::Post, handler)
|
self.on(MethodFilter::Post, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on<H, B, T>(
|
pub fn on<H, T>(self, method: MethodFilter, handler: H) -> OnMethod<IntoService<H, T>, Self>
|
||||||
self,
|
|
||||||
method: MethodFilter,
|
|
||||||
handler: H,
|
|
||||||
) -> OnMethod<IntoService<H, B, T>, Self>
|
|
||||||
where
|
where
|
||||||
H: Handler<B, T>,
|
H: Handler<T>,
|
||||||
{
|
{
|
||||||
OnMethod {
|
OnMethod {
|
||||||
method,
|
method,
|
||||||
|
|
|
@ -637,7 +637,7 @@ pub trait ServiceExt<B>: Service<Request<Body>, Response = Response<B>> {
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnOnce(Self::Error) -> Res,
|
F: FnOnce(Self::Error) -> Res,
|
||||||
Res: IntoResponse<Body>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,29 +5,28 @@ use serde::Serialize;
|
||||||
use std::{borrow::Cow, convert::Infallible};
|
use std::{borrow::Cow, convert::Infallible};
|
||||||
use tower::util::Either;
|
use tower::util::Either;
|
||||||
|
|
||||||
// TODO(david): can we change this to not be generic over the body and just use hyper::Body?
|
pub trait IntoResponse {
|
||||||
pub trait IntoResponse<B> {
|
fn into_response(self) -> Response<Body>;
|
||||||
fn into_response(self) -> Response<B>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for () {
|
impl IntoResponse for () {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
Response::new(Body::empty())
|
Response::new(Body::empty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> IntoResponse<B> for Infallible {
|
impl IntoResponse for Infallible {
|
||||||
fn into_response(self) -> Response<B> {
|
fn into_response(self) -> Response<Body> {
|
||||||
match self {}
|
match self {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, K, B> IntoResponse<B> for Either<T, K>
|
impl<T, K> IntoResponse for Either<T, K>
|
||||||
where
|
where
|
||||||
T: IntoResponse<B>,
|
T: IntoResponse,
|
||||||
K: IntoResponse<B>,
|
K: IntoResponse,
|
||||||
{
|
{
|
||||||
fn into_response(self) -> Response<B> {
|
fn into_response(self) -> Response<Body> {
|
||||||
match self {
|
match self {
|
||||||
Either::A(inner) => inner.into_response(),
|
Either::A(inner) => inner.into_response(),
|
||||||
Either::B(inner) => inner.into_response(),
|
Either::B(inner) => inner.into_response(),
|
||||||
|
@ -35,12 +34,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, T, E> IntoResponse<B> for Result<T, E>
|
impl<T, E> IntoResponse for Result<T, E>
|
||||||
where
|
where
|
||||||
T: IntoResponse<B>,
|
T: IntoResponse,
|
||||||
E: IntoResponse<B>,
|
E: IntoResponse,
|
||||||
{
|
{
|
||||||
fn into_response(self) -> Response<B> {
|
fn into_response(self) -> Response<Body> {
|
||||||
match self {
|
match self {
|
||||||
Ok(value) => value.into_response(),
|
Ok(value) => value.into_response(),
|
||||||
Err(err) => err.into_response(),
|
Err(err) => err.into_response(),
|
||||||
|
@ -48,27 +47,27 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B> IntoResponse<B> for Response<B> {
|
impl IntoResponse for Response<Body> {
|
||||||
fn into_response(self) -> Self {
|
fn into_response(self) -> Self {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for &'static str {
|
impl IntoResponse for &'static str {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
Cow::Borrowed(self).into_response()
|
Cow::Borrowed(self).into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for String {
|
impl IntoResponse for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
Cow::<'static, str>::Owned(self).into_response()
|
Cow::<'static, str>::Owned(self).into_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for std::borrow::Cow<'static, str> {
|
impl IntoResponse for std::borrow::Cow<'static, str> {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
let mut res = Response::new(Body::from(self));
|
let mut res = Response::new(Body::from(self));
|
||||||
res.headers_mut()
|
res.headers_mut()
|
||||||
|
@ -77,7 +76,7 @@ impl IntoResponse<Body> for std::borrow::Cow<'static, str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for Bytes {
|
impl IntoResponse for Bytes {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
let mut res = Response::new(Body::from(self));
|
let mut res = Response::new(Body::from(self));
|
||||||
res.headers_mut().insert(
|
res.headers_mut().insert(
|
||||||
|
@ -88,7 +87,7 @@ impl IntoResponse<Body> for Bytes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for &'static [u8] {
|
impl IntoResponse for &'static [u8] {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
let mut res = Response::new(Body::from(self));
|
let mut res = Response::new(Body::from(self));
|
||||||
res.headers_mut().insert(
|
res.headers_mut().insert(
|
||||||
|
@ -99,7 +98,7 @@ impl IntoResponse<Body> for &'static [u8] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for Vec<u8> {
|
impl IntoResponse for Vec<u8> {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
let mut res = Response::new(Body::from(self));
|
let mut res = Response::new(Body::from(self));
|
||||||
res.headers_mut().insert(
|
res.headers_mut().insert(
|
||||||
|
@ -110,7 +109,7 @@ impl IntoResponse<Body> for Vec<u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for std::borrow::Cow<'static, [u8]> {
|
impl IntoResponse for std::borrow::Cow<'static, [u8]> {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
let mut res = Response::new(Body::from(self));
|
let mut res = Response::new(Body::from(self));
|
||||||
res.headers_mut().insert(
|
res.headers_mut().insert(
|
||||||
|
@ -121,7 +120,7 @@ impl IntoResponse<Body> for std::borrow::Cow<'static, [u8]> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoResponse<Body> for StatusCode {
|
impl IntoResponse for StatusCode {
|
||||||
fn into_response(self) -> Response<Body> {
|
fn into_response(self) -> Response<Body> {
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.status(self)
|
.status(self)
|
||||||
|
@ -130,7 +129,7 @@ impl IntoResponse<Body> for StatusCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IntoResponse<Body> for (StatusCode, T)
|
impl<T> IntoResponse for (StatusCode, T)
|
||||||
where
|
where
|
||||||
T: Into<Body>,
|
T: Into<Body>,
|
||||||
{
|
{
|
||||||
|
@ -142,7 +141,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IntoResponse<Body> for (StatusCode, HeaderMap, T)
|
impl<T> IntoResponse for (StatusCode, HeaderMap, T)
|
||||||
where
|
where
|
||||||
T: Into<Body>,
|
T: Into<Body>,
|
||||||
{
|
{
|
||||||
|
@ -156,7 +155,7 @@ where
|
||||||
|
|
||||||
pub struct Html<T>(pub T);
|
pub struct Html<T>(pub T);
|
||||||
|
|
||||||
impl<T> IntoResponse<Body> for Html<T>
|
impl<T> IntoResponse for Html<T>
|
||||||
where
|
where
|
||||||
T: Into<Body>,
|
T: Into<Body>,
|
||||||
{
|
{
|
||||||
|
@ -170,7 +169,7 @@ where
|
||||||
|
|
||||||
pub struct Json<T>(pub T);
|
pub struct Json<T>(pub T);
|
||||||
|
|
||||||
impl<T> IntoResponse<Body> for Json<T>
|
impl<T> IntoResponse for Json<T>
|
||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
|
|
|
@ -389,7 +389,7 @@ impl<S> Layered<S> {
|
||||||
where
|
where
|
||||||
S: Service<Request<Body>, Response = Response<B>> + Clone,
|
S: Service<Request<Body>, Response = Response<B>> + Clone,
|
||||||
F: FnOnce(S::Error) -> Res,
|
F: FnOnce(S::Error) -> Res,
|
||||||
Res: IntoResponse<Body>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
@ -428,7 +428,7 @@ impl<S, F, B, Res> Service<Request<Body>> for HandleError<S, F>
|
||||||
where
|
where
|
||||||
S: Service<Request<Body>, Response = Response<B>> + Clone,
|
S: Service<Request<Body>, Response = Response<B>> + Clone,
|
||||||
F: FnOnce(S::Error) -> Res + Clone,
|
F: FnOnce(S::Error) -> Res + Clone,
|
||||||
Res: IntoResponse<Body>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
@ -459,7 +459,7 @@ impl<Fut, F, B, E, Res> Future for HandleErrorFuture<Fut, F>
|
||||||
where
|
where
|
||||||
Fut: Future<Output = Result<Response<B>, E>>,
|
Fut: Future<Output = Result<Response<B>, E>>,
|
||||||
F: FnOnce(E) -> Res,
|
F: FnOnce(E) -> Res,
|
||||||
Res: IntoResponse<Body>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,10 +105,12 @@ where
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct HandleError<S, F> {
|
pub struct HandleError<S, F> {
|
||||||
inner: S,
|
pub(crate) inner: S,
|
||||||
f: F,
|
pub(crate) f: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S, F> crate::routing::RoutingDsl for HandleError<S, F> {}
|
||||||
|
|
||||||
impl<S, F> HandleError<S, F> {
|
impl<S, F> HandleError<S, F> {
|
||||||
pub(crate) fn new(inner: S, f: F) -> Self {
|
pub(crate) fn new(inner: S, f: F) -> Self {
|
||||||
Self { inner, f }
|
Self { inner, f }
|
||||||
|
@ -131,7 +133,7 @@ impl<S, F, B, Res> Service<Request<Body>> for HandleError<S, F>
|
||||||
where
|
where
|
||||||
S: Service<Request<Body>, Response = Response<B>> + Clone,
|
S: Service<Request<Body>, Response = Response<B>> + Clone,
|
||||||
F: FnOnce(S::Error) -> Res + Clone,
|
F: FnOnce(S::Error) -> Res + Clone,
|
||||||
Res: IntoResponse<Body>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
@ -162,7 +164,7 @@ impl<Fut, F, E, B, Res> Future for HandleErrorFuture<Fut, F>
|
||||||
where
|
where
|
||||||
Fut: Future<Output = Result<Response<B>, E>>,
|
Fut: Future<Output = Result<Response<B>, E>>,
|
||||||
F: FnOnce(E) -> Res,
|
F: FnOnce(E) -> Res,
|
||||||
Res: IntoResponse<Body>,
|
Res: IntoResponse,
|
||||||
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
|
||||||
B::Error: Into<BoxError> + Send + Sync + 'static,
|
B::Error: Into<BoxError> + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
|
11
src/tests.rs
11
src/tests.rs
|
@ -8,7 +8,7 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
use tower::{make::Shared, BoxError, Service, ServiceBuilder};
|
use tower::{make::Shared, BoxError, Service, ServiceBuilder};
|
||||||
use tower_http::compression::CompressionLayer;
|
use tower_http::{compression::CompressionLayer, trace::TraceLayer};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn hello_world() {
|
async fn hello_world() {
|
||||||
|
@ -444,8 +444,6 @@ async fn middleware_on_single_route() {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handling_errors_from_layered_single_routes() {
|
async fn handling_errors_from_layered_single_routes() {
|
||||||
use tower::timeout::TimeoutLayer;
|
|
||||||
|
|
||||||
async fn handle(_req: Request<Body>) -> &'static str {
|
async fn handle(_req: Request<Body>) -> &'static str {
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
tokio::time::sleep(Duration::from_secs(10)).await;
|
||||||
""
|
""
|
||||||
|
@ -454,7 +452,12 @@ async fn handling_errors_from_layered_single_routes() {
|
||||||
let app = route(
|
let app = route(
|
||||||
"/",
|
"/",
|
||||||
get(handle
|
get(handle
|
||||||
.layer(TimeoutLayer::new(Duration::from_millis(100)))
|
.layer(
|
||||||
|
ServiceBuilder::new()
|
||||||
|
.timeout(Duration::from_secs(30))
|
||||||
|
.layer(TraceLayer::new_for_http())
|
||||||
|
.into_inner(),
|
||||||
|
)
|
||||||
.handle_error(|_error: BoxError| StatusCode::INTERNAL_SERVER_ERROR)),
|
.handle_error(|_error: BoxError| StatusCode::INTERNAL_SERVER_ERROR)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue