everymap_providers_mapbox/domain/tiling/
mod.rs1use crate::client::MapBoxClient;
2use async_trait::async_trait;
3use everymap_core::domains::tiling::{TileOptions, TileProvider, TileResponse};
4use everymap_core::error::EveryMapResult;
5use std::sync::Arc;
6
7const MAP_BASE_URL: &str = "https://api.mapbox.com";
8
9pub struct MapBoxTileProvider {
11 pub(crate) client: Arc<MapBoxClient>,
12 pub(crate) base_url: String,
13}
14
15impl MapBoxTileProvider {
16 pub fn new(client: Arc<MapBoxClient>) -> Self {
17 Self {
18 client,
19 base_url: MAP_BASE_URL.to_string(),
20 }
21 }
22
23 pub fn with_base_url(client: Arc<MapBoxClient>, base_url: String) -> Self {
24 Self { client, base_url }
25 }
26}
27
28#[async_trait]
29impl TileProvider for MapBoxTileProvider {
30 async fn get_tile(
31 &self,
32 z: u32,
33 x: u32,
34 y: u32,
35 options: &TileOptions,
36 ) -> EveryMapResult<TileResponse> {
37 let tileset_id = options
38 .provider_extra
39 .as_ref()
40 .and_then(|e| e.get("tileset_id"))
41 .and_then(|v| v.as_str())
42 .unwrap_or("mapbox.mapbox-streets-v8");
43 let format = options.format.as_deref().unwrap_or("mvt");
44
45 let url = format!(
46 "{}/v4/{}/{}/{}/{}.{}",
47 self.base_url, tileset_id, z, x, y, format
48 );
49
50 let builder = self.client.build_request(reqwest::Method::GET, &url);
51
52 let response = self.client.request(builder).await?;
53
54 let content_type = response
55 .headers()
56 .get("content-type")
57 .and_then(|v| v.to_str().ok())
58 .map(|s| s.split(';').next().unwrap_or(s).trim().to_string());
59
60 let data = response.bytes().await?.to_vec();
61
62 Ok(TileResponse { data, content_type })
63 }
64}