use axum::extract::{Path, State}; use axum::{ body::Body, extract::Host, http::Request, response::Html, routing::any, Extension, Router, }; use std::sync::Arc; use std::{ net::SocketAddr, sync::atomic::{AtomicUsize, Ordering}, }; use tower::ServiceExt; struct AppState { api_requests: AtomicUsize, website_requests: AtomicUsize, } #[tokio::main] async fn main() { let state = Arc::new(AppState { website_requests: AtomicUsize::new(0), api_requests: AtomicUsize::new(0), }); let api_router = Router::new() .route("/*path", any(api_handler)) .with_state(state.clone()); let website_router = Router::new() .route("/*path", any(website_handler)) .with_state(state); let app = Router::new().route( "/*every_path", any(|Host(host): Host, request: Request| async move { let hostname = if let Some((hostname, _port)) = host.split_once(':') { hostname } else { &host }; println!("{}", hostname); match hostname { "apps4u.local" => api_router.oneshot(request).await, _ => website_router.oneshot(request).await, } }), ); let addr = SocketAddr::from(([127, 0, 0, 1], 8080)); let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); println!("listening on {}", addr); axum::serve(listener, app).await.unwrap(); } //async fn api_handler(Extension(state): Extension>) -> Html { async fn api_handler( Path((_every_path, path)): Path<(String, String)>, State(state): State>, ) -> Html { println!("Match path {}", path); state.api_requests.fetch_add(1, Ordering::SeqCst); Html(format!( "api: {}", state.api_requests.load(Ordering::SeqCst) )) } //async fn website_handler(Extension(state): Extension>) -> Html { async fn website_handler( Path((_every_path, path)): Path<(String, String)>, State(state): State>, ) -> Html { println!("Match path {}", path); state.website_requests.fetch_add(1, Ordering::SeqCst); Html(format!( "website: {}", state.website_requests.load(Ordering::SeqCst) )) }