axum-reverse-proxy 1.2.0

A flexible and efficient reverse proxy implementation for Axum web applications
Documentation
use crate::proxy::ReverseProxy;
use axum::routing::Router;
use hyper_util::client::legacy::connect::Connect;

/// Enables conversion from a `ReverseProxy` into an Axum `Router`.
///
/// This implementation allows the reverse proxy to be easily integrated into an Axum
/// application. It handles:
///
/// - Path-based routing using the configured base path
/// - State management using `Arc` for thread-safety
/// - Fallback handling for all HTTP methods
///
/// # Example
///
/// ```rust
/// use axum::Router;
/// use axum_reverse_proxy::ReverseProxy;
///
/// let proxy = ReverseProxy::new("/api", "https://api.example.com");
/// let app: Router = proxy.into();
/// ```
impl<C, S> From<ReverseProxy<C>> for Router<S>
where
    C: Connect + Clone + Send + Sync + 'static,
    S: Send + Sync + Clone + 'static,
{
    fn from(proxy: ReverseProxy<C>) -> Self {
        let path = proxy.path().to_string();
        let proxy_router = Router::<S>::new().fallback_service(proxy);

        if ["", "/"].contains(&path.as_str()) {
            proxy_router
        } else {
            Router::new().nest(&path, proxy_router)
        }
    }
}

use crate::balanced_proxy::{BalancedProxy, DiscoverableBalancedProxy};

impl<C, S> From<BalancedProxy<C>> for Router<S>
where
    C: Connect + Clone + Send + Sync + 'static,
    S: Send + Sync + Clone + 'static,
{
    fn from(proxy: BalancedProxy<C>) -> Self {
        let path = proxy.path().to_string();
        let proxy_router = Router::<S>::new().fallback_service(proxy);

        if ["", "/"].contains(&path.as_str()) {
            proxy_router
        } else {
            Router::new().nest(&path, proxy_router)
        }
    }
}

impl<C, D, S> From<DiscoverableBalancedProxy<C, D>> for Router<S>
where
    C: Connect + Clone + Send + Sync + 'static,
    D: tower::discover::Discover + Clone + Send + Sync + 'static,
    D::Service: Into<String> + Send,
    D::Key: Clone + std::fmt::Debug + Send + Sync + std::hash::Hash,
    D::Error: std::fmt::Debug + Send,
    S: Send + Sync + Clone + 'static,
{
    fn from(proxy: DiscoverableBalancedProxy<C, D>) -> Self {
        let path = proxy.path().to_string();
        let proxy_router = Router::<S>::new().fallback_service(proxy);

        if ["", "/"].contains(&path.as_str()) {
            proxy_router
        } else {
            Router::new().nest(&path, proxy_router)
        }
    }
}