use crate::config::{Config, Source};
use crate::reader::TileReader;
use crate::reader::local::LocalTileReader;
use crate::routes::{get_all_layers, tile_handler, webmap_handler};
use axum::{Router, routing::get};
use std::net::SocketAddr;
use std::sync::Arc;
pub struct TileServer {
config: Config,
reader: Arc<dyn TileReader>,
}
impl TileServer {
pub fn new(config: Config) -> anyhow::Result<Self> {
let reader: Arc<dyn TileReader> = match &config.source {
Some(Source::Local(path)) => Arc::new(LocalTileReader::new(path.clone())),
Some(Source::S3 { .. }) => unimplemented!("S3 backend is not yet implemented"),
None => anyhow::bail!("No source provided in the configuration"),
};
Ok(Self { config, reader })
}
pub async fn start(self) -> anyhow::Result<()> {
let app = Router::new()
.route("/tiles/{layer}/{z}/{x}/{y}", get(tile_handler))
.route("/layers", get(get_all_layers))
.route("/map", get(webmap_handler))
.with_state(self.reader.clone());
let addr = SocketAddr::from(([0, 0, 0, 0], self.config.port));
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
let layers = self.reader.list_layers().await;
let random_layer = layers.first().unwrap().layer.clone();
println!(
r#"
π TileYolo serving on {}
πΊοΈ QGIS XYZ-tiles path (on randomly picked layer: {})
β http://{}/tiles/{}/{{z}}/{{x}}/{{y}}
π Browse all loaded layers visually
β http://{}/map
π Query for all layers (JSON)
β http://{}/layers
"#,
addr, random_layer, addr, random_layer, addr, addr
);
axum::serve(listener, app.into_make_service())
.await
.unwrap();
Ok(())
}
}