bbox_tile_server/datasource/
wms_http.rs1use crate::config::WmsHttpSourceParamsCfg;
4use crate::datasource::{
5 wms_fcgi::HttpRequestParams, LayerInfo, SourceType, TileSource, TileSourceError,
6};
7use crate::filter_params::FilterParams;
8use crate::service::TmsExtensions;
9use async_trait::async_trait;
10use bbox_core::config::WmsHttpSourceProviderCfg;
11use bbox_core::{Format, TileResponse};
12use log::debug;
13use std::io::Cursor;
14use tile_grid::{BoundingBox, Tms, Xyz};
15use tilejson::{tilejson, TileJSON};
16
17#[derive(Clone, Debug)]
18pub struct WmsHttpSource {
19 client: reqwest::Client,
20 pub req_url: String,
21}
22
23impl WmsHttpSource {
24 pub fn from_config(
25 provider: &WmsHttpSourceProviderCfg,
26 params: &WmsHttpSourceParamsCfg,
27 srid: i32,
28 ) -> Self {
29 let client = reqwest::Client::new();
30 let req_url = format!(
31 "{}&SERVICE=WMS&REQUEST=GetMap&CRS=EPSG:{}&WIDTH={}&HEIGHT={}&LAYERS={}&STYLES=&FORMAT={}",
32 provider.baseurl,
33 srid,
34 256, 256, params.layers,
37 provider.format,
38 );
39 WmsHttpSource { client, req_url }
40 }
41 fn get_map_request(&self, extent: &BoundingBox) -> String {
42 format!(
43 "{}&BBOX={},{},{},{}",
44 self.req_url, extent.left, extent.bottom, extent.right, extent.top
45 )
46 }
47
48 pub async fn get_map_response(
49 &self,
50 extent: &BoundingBox,
51 ) -> Result<reqwest::Response, TileSourceError> {
52 let req = self.get_map_request(extent);
53 debug!("Request {req}");
54 self.client.get(req).send().await.map_err(Into::into)
55 }
56
57 async fn bbox_request(&self, extent: &BoundingBox) -> Result<TileResponse, TileSourceError> {
58 let wms_resp = self.get_map_response(extent).await?;
59 let mut response = TileResponse::new();
60 if let Some(content_type) = wms_resp
61 .headers()
62 .get("content-type")
63 .map(|ct| ct.to_str().expect("invalid content-type"))
64 {
65 response.set_content_type(content_type);
66 }
67 let body = Box::new(Cursor::new(wms_resp.bytes().await?));
68 Ok(response.with_body(body))
69 }
70}
71
72#[async_trait]
73impl TileSource for WmsHttpSource {
74 async fn xyz_request(
75 &self,
76 tms: &Tms,
77 tile: &Xyz,
78 _filter: &FilterParams,
79 _format: &Format,
80 _request_params: HttpRequestParams<'_>,
81 ) -> Result<TileResponse, TileSourceError> {
82 let extent_info = tms.xyz_extent(tile)?;
83 self.bbox_request(&extent_info.extent).await
84 }
85 fn source_type(&self) -> SourceType {
86 SourceType::Raster
87 }
88 async fn tilejson(&self, _tms: &Tms, format: &Format) -> Result<TileJSON, TileSourceError> {
89 let mut tj = tilejson! { tiles: vec![] };
90 tj.other
91 .insert("format".to_string(), format.file_suffix().into());
92 Ok(tj)
93 }
94 async fn layers(&self) -> Result<Vec<LayerInfo>, TileSourceError> {
95 Ok(vec![LayerInfo {
96 name: "WmsHttpSource".to_string(), geometry_type: None,
98 style: None,
99 }])
100 }
101}