68 lines
1.8 KiB
Rust
68 lines
1.8 KiB
Rust
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<dyn std::error::Error>> {
|
|
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<String>) -> Result<impl IntoResponse, StatusCode> {
|
|
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))
|
|
}
|