//! Async functions that can be used to handle requests. use crate::{ body::{box_body, BoxBody}, extract::FromRequest, response::IntoResponse, routing::{EmptyRouter, MethodFilter, RouteFuture}, service::HandleError, }; use async_trait::async_trait; use bytes::Bytes; use http::{Request, Response}; use std::{ convert::Infallible, fmt, future::Future, marker::PhantomData, task::{Context, Poll}, }; use tower::{BoxError, Layer, Service, ServiceExt}; pub mod future; /// Route requests to the given handler regardless of the HTTP method of the /// request. /// /// # Example /// /// ```rust /// use axum::prelude::*; /// /// async fn handler() {} /// /// // All requests to `/` will go to `handler` regardless of the HTTP method. /// let app = route("/", any(handler)); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` 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 axum::prelude::*; /// /// async fn handler() {} /// /// // Requests to `GET /` will go to `handler`. /// let app = route("/", get(handler)); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` 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 axum::{handler::on, routing::MethodFilter, prelude::*}; /// /// async fn handler() {} /// /// // Requests to `POST /` will go to `handler`. /// let app = route("/", on(MethodFilter::Post, handler)); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` pub fn on(method: MethodFilter, handler: H) -> OnMethod, EmptyRouter> where H: Handler, { OnMethod { method, svc: handler.into_service(), fallback: EmptyRouter::method_not_allowed(), } } pub(crate) 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. /// /// See the [module docs](crate::handler) for more details. #[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. /// /// All requests to the handler will be processed by the layer's /// corresponding middleware. /// /// This can be used to add additional processing to a request for a single /// handler. /// /// Note this differes from [`routing::Layered`](crate::routing::Layered) /// which adds a middleware to a group of routes. /// /// # Example /// /// Adding the [`tower::limit::ConcurrencyLimit`] middleware to a handler /// can be done like so: /// /// ```rust /// use axum::prelude::*; /// use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit}; /// /// async fn handler() { /* ... */ } /// /// let layered_handler = handler.layer(ConcurrencyLimitLayer::new(64)); /// let app = route("/", get(layered_handler)); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` /// /// When adding middleware that might fail its recommended 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() -> Fut + Send + Sync, Fut: Future + Send, Res: IntoResponse, B: Send + 'static, { type Sealed = sealed::Hidden; async fn call(self, _req: Request) -> Response { self().await.into_response().map(box_body) } } macro_rules! impl_handler { () => { }; ( $head:ident, $($tail:ident),* $(,)? ) => { #[async_trait] #[allow(non_snake_case)] impl Handler for F where F: FnOnce($head, $($tail,)*) -> Fut + Send + Sync, Fut: Future + Send, B: Send + 'static, Res: IntoResponse, $head: FromRequest + Send, $( $tail: FromRequest + Send, )* { type Sealed = sealed::Hidden; async fn call(self, req: Request) -> Response { let mut req = crate::extract::RequestParts::new(req); let $head = match $head::from_request(&mut req).await { Ok(value) => value, Err(rejection) => return rejection.into_response().map(crate::body::box_body), }; $( let $tail = match $tail::from_request(&mut req).await { Ok(value) => value, Err(rejection) => return rejection.into_response().map(crate::body::box_body), }; )* let res = self($head, $($tail,)*).await; res.into_response().map(crate::body::box_body) } } impl_handler!($($tail,)*); }; } impl_handler!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16); /// A [`Service`] created from a [`Handler`] by applying a Tower middleware. /// /// Created with [`Handler::layer`]. See that method for more details. pub struct Layered { svc: S, _input: PhantomData T>, } impl fmt::Debug for Layered where S: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Layered").field("svc", &self.svc).finish() } } impl Clone for Layered where S: Clone, { fn clone(&self) -> Self { Self::new(self.svc.clone()) } } #[async_trait] impl Handler for Layered where S: Service, Response = Response> + Send, S::Error: IntoResponse, S::Future: Send, ReqBody: Send + 'static, ResBody: http_body::Body + Send + Sync + 'static, ResBody::Error: Into + Send + Sync + 'static, { type Sealed = sealed::Hidden; async fn call(self, req: Request) -> Response { match self .svc .oneshot(req) .await .map_err(IntoResponse::into_response) { Ok(res) => res.map(box_body), Err(res) => res.map(box_body), } } } impl Layered { pub(crate) fn new(svc: S) -> Self { Self { svc, _input: PhantomData, } } /// Create a new [`Layered`] handler where errors will be handled using the /// given closure. /// /// This is used to convert errors to responses rather than simply /// terminating the connection. /// /// It works similarly to [`routing::Layered::handle_error`]. See that for more details. /// /// [`routing::Layered::handle_error`]: crate::routing::Layered::handle_error pub fn handle_error( self, f: F, ) -> Layered, T> where S: Service, Response = Response>, F: FnOnce(S::Error) -> Result, Res: IntoResponse, { let svc = HandleError::new(self.svc, f); Layered::new(svc) } } /// An adapter that makes a [`Handler`] into a [`Service`]. /// /// Created with [`Handler::into_service`]. pub struct IntoService { handler: H, _marker: PhantomData (B, T)>, } impl IntoService { fn new(handler: H) -> Self { Self { handler, _marker: PhantomData, } } } impl fmt::Debug for IntoService where H: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntoService") .field("handler", &self.handler) .finish() } } impl Clone for IntoService where H: Clone, { fn clone(&self) -> Self { Self { handler: self.handler.clone(), _marker: PhantomData, } } } impl Service> for IntoService where H: Handler + Clone + Send + 'static, B: Send + 'static, { type Response = Response; type Error = Infallible; type Future = future::IntoServiceFuture; fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { // `IntoService` can only be constructed from async functions which are always ready, or from // `Layered` which bufferes in `::call` and is therefore also always // ready. Poll::Ready(Ok(())) } fn call(&mut self, req: Request) -> Self::Future { let handler = self.handler.clone(); let future = Box::pin(async move { let res = Handler::call(handler, req).await; Ok(res) }); future::IntoServiceFuture { future } } } /// A handler [`Service`] that accepts requests based on a [`MethodFilter`] and /// allows chaining additional handlers. #[derive(Debug, Clone, Copy)] pub struct OnMethod { pub(crate) method: MethodFilter, pub(crate) svc: S, pub(crate) fallback: F, } impl OnMethod { /// Chain an additional handler that will accept all requests regardless of /// its HTTP method. /// /// See [`OnMethod::get`] for an example. pub fn any(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Any, handler) } /// Chain an additional handler that will only accept `CONNECT` requests. /// /// See [`OnMethod::get`] for an example. pub fn connect(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Connect, handler) } /// Chain an additional handler that will only accept `DELETE` requests. /// /// See [`OnMethod::get`] for an example. pub fn delete(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Delete, handler) } /// Chain an additional handler that will only accept `GET` requests. /// /// # Example /// /// ```rust /// use axum::prelude::*; /// /// async fn handler() {} /// /// async fn other_handler() {} /// /// // Requests to `GET /` will go to `handler` and `POST /` will go to /// // `other_handler`. /// let app = route("/", post(handler).get(other_handler)); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` pub fn get(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Get, handler) } /// Chain an additional handler that will only accept `HEAD` requests. /// /// See [`OnMethod::get`] for an example. pub fn head(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Head, handler) } /// Chain an additional handler that will only accept `OPTIONS` requests. /// /// See [`OnMethod::get`] for an example. pub fn options(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Options, handler) } /// Chain an additional handler that will only accept `PATCH` requests. /// /// See [`OnMethod::get`] for an example. pub fn patch(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Patch, handler) } /// Chain an additional handler that will only accept `POST` requests. /// /// See [`OnMethod::get`] for an example. pub fn post(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Post, handler) } /// Chain an additional handler that will only accept `PUT` requests. /// /// See [`OnMethod::get`] for an example. pub fn put(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Put, handler) } /// Chain an additional handler that will only accept `TRACE` requests. /// /// See [`OnMethod::get`] for an example. pub fn trace(self, handler: H) -> OnMethod, Self> where H: Handler, { self.on(MethodFilter::Trace, handler) } /// Chain an additional handler that will accept requests matching the given /// `MethodFilter`. /// /// # Example /// /// ```rust /// use axum::{routing::MethodFilter, prelude::*}; /// /// async fn handler() {} /// /// async fn other_handler() {} /// /// // Requests to `GET /` will go to `handler` and `DELETE /` will go to /// // `other_handler` /// let app = route("/", get(handler).on(MethodFilter::Delete, other_handler)); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` pub fn on( self, method: MethodFilter, handler: H, ) -> OnMethod, Self> where H: Handler, { OnMethod { method, svc: handler.into_service(), fallback: self, } } } impl Service> for OnMethod where S: Service, Response = Response, Error = Infallible> + Clone, F: Service, Response = Response, Error = Infallible> + Clone, { type Response = Response; type Error = Infallible; type Future = RouteFuture; fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: Request) -> Self::Future { if self.method.matches(req.method()) { let fut = self.svc.clone().oneshot(req); RouteFuture::a(fut) } else { let fut = self.fallback.clone().oneshot(req); RouteFuture::b(fut) } } }