//! Async functions that can be used to handle requests.
use crate::{
body::{Body, BoxBody},
extract::FromRequest,
response::IntoResponse,
routing::{BoxResponseBody, EmptyRouter, MethodFilter, RouteFuture},
service::HandleError,
};
use async_trait::async_trait;
use bytes::Bytes;
use futures_util::future;
use http::{Request, Response};
use std::{
convert::Infallible,
fmt,
future::Future,
marker::PhantomData,
task::{Context, Poll},
};
use tower::{BoxError, Layer, Service, ServiceExt};
/// Route requests to the given handler regardless of the HTTP method of the
/// request.
///
/// # Example
///
/// ```rust
/// use tower_web::prelude::*;
///
/// async fn handler(request: Request
) {}
///
/// // All requests to `/` will go to `handler` regardless of the HTTP method.
/// let app = route("/", any(handler));
/// ```
pub fn any(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Any, handler)
}
/// Route `CONNECT` requests to the given handler.
///
/// See [`get`] for an example.
pub fn connect(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Connect, handler)
}
/// Route `DELETE` requests to the given handler.
///
/// See [`get`] for an example.
pub fn delete(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Delete, handler)
}
/// Route `GET` requests to the given handler.
///
/// # Example
///
/// ```rust
/// use tower_web::prelude::*;
///
/// async fn handler(request: Request) {}
///
/// // Requests to `GET /` will go to `handler`.
/// let app = route("/", get(handler));
/// ```
pub fn get(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Get, handler)
}
/// Route `HEAD` requests to the given handler.
///
/// See [`get`] for an example.
pub fn head(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Head, handler)
}
/// Route `OPTIONS` requests to the given handler.
///
/// See [`get`] for an example.
pub fn options(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Options, handler)
}
/// Route `PATCH` requests to the given handler.
///
/// See [`get`] for an example.
pub fn patch(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Patch, handler)
}
/// Route `POST` requests to the given handler.
///
/// See [`get`] for an example.
pub fn post(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Post, handler)
}
/// Route `PUT` requests to the given handler.
///
/// See [`get`] for an example.
pub fn put(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Put, handler)
}
/// Route `TRACE` requests to the given handler.
///
/// See [`get`] for an example.
pub fn trace(handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
on(MethodFilter::Trace, handler)
}
/// Route requests with the given method to the handler.
///
/// # Example
///
/// ```rust
/// use tower_web::{handler::on, routing::MethodFilter, prelude::*};
///
/// async fn handler(request: Request) {}
///
/// // Requests to `POST /` will go to `handler`.
/// let app = route("/", on(MethodFilter::Post, handler));
/// ```
pub fn on(method: MethodFilter, handler: H) -> OnMethod, EmptyRouter>
where
H: Handler,
{
OnMethod {
method,
svc: handler.into_service(),
fallback: EmptyRouter,
}
}
mod sealed {
#![allow(unreachable_pub, missing_docs, missing_debug_implementations)]
pub trait HiddentTrait {}
pub struct Hidden;
impl HiddentTrait for Hidden {}
}
/// Trait for async functions that can be used to handle requests.
///
/// You shouldn't need to depend on this trait directly. It is automatically
/// implemented to closures of the right types.
///
/// # Example
///
/// Some examples of handlers:
///
/// ```rust
/// use tower_web::prelude::*;
/// use bytes::Bytes;
/// use http::StatusCode;
///
/// // Handlers must take `Request` as the first argument and must return
/// // something that implements `IntoResponse`, which `()` does
/// async fn unit_handler(request: Request) {}
///
/// // `String` also implements `IntoResponse`
/// async fn string_handler(request: Request) -> String {
/// "Hello, World!".to_string()
/// }
///
/// // Handler the buffers the request body and returns it if it is valid UTF-8
/// async fn buffer_body(request: Request, body: Bytes) -> Result {
/// if let Ok(string) = String::from_utf8(body.to_vec()) {
/// Ok(string)
/// } else {
/// Err(StatusCode::BAD_REQUEST)
/// }
/// }
/// ```
///
/// For more details on generating responses see the
/// [`response`](crate::response) module and for more details on extractors see
/// the [`extract`](crate::extract) module.
#[async_trait]
pub trait Handler: Sized {
// This seals the trait. We cannot use the regular "sealed super trait" approach
// due to coherence.
#[doc(hidden)]
type Sealed: sealed::HiddentTrait;
/// Call the handler with the given request.
async fn call(self, req: Request) -> Response;
/// Apply a [`tower::Layer`] to the handler.
///
/// # Example
///
/// Adding the [`tower::limit::ConcurrencyLimit`] middleware to a handler
/// can be done with [`tower::limit::ConcurrencyLimitLayer`]:
///
/// ```rust
/// use tower_web::prelude::*;
/// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit};
///
/// async fn handler(request: Request) { /* ... */ }
///
/// let layered_handler = handler.layer(ConcurrencyLimitLayer::new(64));
/// ```
///
/// When adding middleware that might fail its required to handle those
/// errors. See [`Layered::handle_error`] for more details.
fn layer(self, layer: L) -> Layered
where
L: Layer>,
{
Layered::new(layer.layer(IntoService::new(self)))
}
/// Convert the handler into a [`Service`].
fn into_service(self) -> IntoService {
IntoService::new(self)
}
}
#[async_trait]
impl Handler<()> for F
where
F: FnOnce(Request) -> Fut + Send + Sync,
Fut: Future