use std::path::PathBuf; use axum::Router; use axum::extract::Path; use axum::response::IntoResponse; use axum::routing::get; use reqwest::StatusCode; use tokio::fs; use tower_http::cors::CorsLayer; #[tokio::main] async fn main() -> Result<(), Box> { let app = Router::new() .route("/{*path}", get(get_file)) .layer(CorsLayer::permissive()); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); axum::serve(listener, app.into_make_service()).await?; Ok(()) } async fn get_file(Path(path): Path) -> Result { let local_path = PathBuf::from("static").join(&path); // Check if file exists if fs::metadata(&local_path).await.is_err() { // Build remote URL let remote_url = format!("https://osm.rrze.fau.de/osmhd/{}", path); // Download file let response = reqwest::get(&remote_url) .await .map_err(|_| StatusCode::BAD_GATEWAY)?; if !response.status().is_success() { return Err(StatusCode::NOT_FOUND); } let bytes = response .bytes() .await .map_err(|_| StatusCode::BAD_GATEWAY)?; // Ensure directory exists if let Some(parent) = local_path.parent() { fs::create_dir_all(parent) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; } // Save file fs::write(&local_path, &bytes) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; } // Serve file let bytes = fs::read(&local_path) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; Ok(([(axum::http::header::CONTENT_TYPE, "image/png")], bytes)) }