diff --git a/bbox-tile-server/README.md b/bbox-tile-server/README.md index 4db9fc03..b028e734 100644 --- a/bbox-tile-server/README.md +++ b/bbox-tile-server/README.md @@ -147,6 +147,10 @@ Style JSON requests: curl -s http://localhost:8080/xyz/ne_extracts.style.json | jq . +Metadata requests: + + curl -s http://localhost:8080/xyz/mbtiles_mvt_fl/metadata.json | jq . + Map viewer examples: x-www-browser http://127.0.0.1:8080/assets/usergrid.html?debug=1 diff --git a/bbox-tile-server/src/config.rs b/bbox-tile-server/src/config.rs index cb61b767..813df308 100644 --- a/bbox-tile-server/src/config.rs +++ b/bbox-tile-server/src/config.rs @@ -20,7 +20,7 @@ pub struct TileserverCfg { pub tilestores: Vec, } -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Clone, Debug)] #[serde(deny_unknown_fields)] pub struct TileSetCfg { pub name: String, diff --git a/bbox-tile-server/src/endpoints.rs b/bbox-tile-server/src/endpoints.rs index 38b5a964..d7773e0b 100644 --- a/bbox-tile-server/src/endpoints.rs +++ b/bbox-tile-server/src/endpoints.rs @@ -9,7 +9,7 @@ use tile_grid::{ Crs, DataType, Link, TileSet, TileSetItem, TileSets, TitleDescriptionKeywords, Xyz, }; -/// XYZ endpoint +/// XYZ tile endpoint // xyz/{tileset}/{z}/{x}/{y}.{format} async fn xyz( service: web::Data, @@ -26,6 +26,7 @@ async fn xyz( } /// XYZ tilejson endpoint +/// TileJSON layer metadata (https://github.com/mapbox/tilejson-spec) // xyz/{tileset}.json async fn tilejson( service: web::Data, @@ -56,6 +57,16 @@ async fn stylejson( } } +/// XYZ MBTiles metadata.json (https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md) +// xyz/{tileset}/metadata.json +async fn metadatajson(service: web::Data, tileset: web::Path) -> HttpResponse { + if let Ok(metadata) = service.mbtiles_metadata(&tileset).await { + HttpResponse::Ok().json(metadata) + } else { + HttpResponse::InternalServerError().finish() + } +} + /// Map tile endpoint // map/tiles/{tileMatrixSetId}/{tileMatrix}/{tileRow}/{tileCol} async fn map_tile( @@ -280,6 +291,9 @@ impl TileService { ) .service(web::resource("/xyz/{tileset}.style.json").route(web::get().to(stylejson))) .service(web::resource("/xyz/{tileset}.json").route(web::get().to(tilejson))) + .service( + web::resource("/xyz/{tileset}/metadata.json").route(web::get().to(metadatajson)), + ) .service( web::resource("/map/tiles/{tileMatrixSetId}/{tileMatrix}/{tileRow}/{tileCol}") .route(web::get().to(map_tile)), diff --git a/bbox-tile-server/src/service.rs b/bbox-tile-server/src/service.rs index eee8b7c9..35d3e269 100644 --- a/bbox-tile-server/src/service.rs +++ b/bbox-tile-server/src/service.rs @@ -15,6 +15,7 @@ use bbox_core::ogcapi::ApiLink; use bbox_core::service::{CoreService, OgcApiService}; use bbox_core::Format; use clap::{ArgMatches, FromArgMatches}; +use martin_mbtiles::Metadata; use once_cell::sync::OnceCell; use serde_json::json; use std::collections::HashMap; @@ -41,6 +42,7 @@ pub struct TileSet { format: Format, pub store_reader: Option>, pub store_writer: Option>, + config: TileSetCfg, cache_cfg: Option, cache_limits: Option, } @@ -133,10 +135,10 @@ impl OgcApiService for TileService { .mbtiles_metadata(&ts, &format) .await .unwrap_or_else(error_exit); - let cache_cfg = ts.cache.map(|name| { + let cache_cfg = ts.cache.as_ref().map(|name| { stores - .get(&name) - .unwrap_or_else(|| error_exit(ServiceError::CacheNotFound(name))) + .get(name) + .unwrap_or_else(|| error_exit(ServiceError::CacheNotFound(name.to_string()))) }); let store_writer = if let Some(config) = cache_cfg { Some(store_writer_from_config(config, &ts.name, &format, metadata).await) @@ -154,6 +156,7 @@ impl OgcApiService for TileService { format, store_reader, store_writer, + config: ts.clone(), cache_cfg: cache_cfg.cloned(), cache_limits: ts.cache_limits, }; @@ -369,6 +372,15 @@ impl TileService { )); Ok(tilejson) } + + /// MBTiles metadata.json + pub async fn mbtiles_metadata(&self, tileset: &str) -> Result { + let ts = self + .tileset(tileset) + .ok_or(ServiceError::TilesetNotFound(tileset.to_string()))?; + Ok(ts.source.mbtiles_metadata(&ts.config, &ts.format).await?) + } + /// Autogenerated Style JSON (https://www.mapbox.com/mapbox-gl-style-spec/) pub async fn stylejson( &self, diff --git a/docs/src/tile-server/endpoints.md b/docs/src/tile-server/endpoints.md index 4caf4bd4..4f2f2489 100644 --- a/docs/src/tile-server/endpoints.md +++ b/docs/src/tile-server/endpoints.md @@ -7,9 +7,10 @@ Services are available via the following HTTP endpoints: | `/tiles` | List of available tilesets | | `/tiles/{tileset}` | Tileset metadata | | `/map/tiles/{tileset}/{z}/{x}/{y}` | Map tiles endpoint | -| `/xyz/{tileset}/{z}/{x}/{y}.{format}` | XYZ endpoint | +| `/xyz/{tileset}/{z}/{x}/{y}.{format}` | XYZ tile endpoint | | `/xyz/{tileset}.json` | Tilejson endpoint | | `/xyz/{tileset}.style.json` | Generic Style JSON endpoint | +| `/xyz/{tileset}/metadata.json` | MBTiles metadata JSON | ## Request examples