webrune 0.1.2

A composable web server.
Documentation
use std::sync::Arc;

use crate::{Flow, IntoResponse, Response};

/// An asynchronous request handler.
///
/// A `Handler` takes an input `I` and some shared state `S`,
/// then asynchronously produces a [`Flow`], which represents either:
/// - a successful output (`Output`), or
/// - an exception (`Exception`) that can be converted into a response.
///
/// Handlers can be *chained* together using [`Handler::then`].
///
/// # Type Parameters
///
/// - `I`: Input type
/// - `S`: Shared state type
pub trait Handler<I, S>: Sized {
    /// The successful output type produced by this handler.
    type Output;

    /// The error type produced by this handler.
    ///
    /// This must be convertible into a response so it can be
    /// sent back to the caller.
    type Exception: IntoResponse;

    /// The future returned by [`handle`](Self::handle).
    type Future: Future<Output = Flow<Self::Output, Self::Exception>>;

    /// Executes the handler with the given input and state.
    ///
    /// Implementations should return a future that resolves
    /// to either a successful output or an exception.
    fn handle(&self, input: I, state: S) -> Self::Future;

    /// Chains this handler with another handler.
    ///
    /// The output of `self` becomes the input of `handler`.
    ///
    /// The returned value implements [`Handler`] itself, allowing
    /// handler chains to be built incrementally.
    ///
    /// The second handler is wrapped in an [`Arc`] so it can be
    /// cheaply cloned and safely shared across async boundaries.
    ///
    /// # Example
    ///
    /// ```ignore
    /// let chain = handler_a.then(handler_b);
    /// ```
    fn then<H>(self, handler: H) -> (Self, Arc<H>)
    where
        H: Handler<Self::Output, S>,
    {
        (self, Arc::new(handler))
    }
}

/// A middleware-like abstraction for transforming handlers.
///
/// A `Layer` takes an existing handler `H` and wraps it with additional
/// behavior, producing a new handler.
///
/// Layers are typically *stackable*, allowing multiple layers to be
/// applied around a handler to form a processing pipeline.
///
/// # Type Parameters
///
/// - `H`: The handler type being wrapped
pub trait Layer<H> {
    /// The handler type produced after applying this layer.
    ///
    /// This is usually another type that implements [`Handler`],
    /// potentially wrapping `H` internally.
    type Handler;

    /// Wraps the given handler with this layer.
    ///
    /// Implementations should return a new handler that delegates
    /// to `handler` while adding the layer’s behavior before,
    /// after, or around its execution.
    fn wrap(self, handler: H) -> Self::Handler;
}

/// Blanket implementation of [`Handler`] for async functions and closures.
///
/// Any function or closure with the signature:
///
/// ```text
/// fn(I, S) -> impl Future<Output = Flow<O, E>>
/// ```
///
/// automatically implements [`Handler<I, S>`], as long as `E`
/// can be converted into a response.
///
/// This allows plain async functions to be used directly as handlers.
impl<F, Fut, I, S, O, E> Handler<I, S> for F
where
    F: Fn(I, S) -> Fut,
    Fut: Future<Output = Flow<O, E>>,
    E: IntoResponse,
{
    type Output = O;
    type Exception = E;
    type Future = Fut;

    /// Invokes the underlying function or closure.
    fn handle(&self, input: I, state: S) -> Self::Future {
        self(input, state)
    }
}

/// [`Handler`] implementation for a chained pair of handlers.
///
/// This represents a pipeline where:
///
/// 1. The first handler (`H0`) is executed with the original input.
/// 2. If successful, its output is passed to the second handler (`H1`).
/// 3. Any exception from either handler is converted into a concrete [`Response`].
///
/// This is the internal type produced by [`Handler::then`].
impl<H0, H1, I, S> Handler<I, S> for (H0, Arc<H1>)
where
    H0: Handler<I, S>,
    H0::Future: 'static,
    H1: Handler<H0::Output, S> + 'static,
    S: Clone + 'static,
{
    /// The final output comes from the second handler.
    type Output = H1::Output;

    /// The unified exception type for the handler chain.
    ///
    /// All handler exceptions are normalized into a [`Response`].
    type Exception = Response;

    /// The future driving the entire handler chain.
    type Future = impl Future<Output = Flow<Self::Output, Self::Exception>> + 'static;

    /// Executes the handler chain.
    ///
    /// The shared state is cloned so it can be reused by both handlers.
    /// Exceptions from either handler are converted into a [`Response`].
    fn handle(&self, input: I, state: S) -> Self::Future {
        // Execute the first handler immediately.
        let future = self.0.handle(input, state.clone());

        // Clone the second handler for use inside the async block.
        let handler = self.1.clone();

        async move {
            // Await the first handler and normalize any exception.
            let output = future.await.map_exception(IntoResponse::into_response)?;

            // Pass the output into the second handler and normalize errors again.
            handler
                .handle(output, state)
                .await
                .map_exception(IntoResponse::into_response)
        }
    }
}