bbox_frontend/
endpoints.rs

1use crate::{themes_json, MapInventory};
2use actix_web::{
3    web::{self, get, resource},
4    Error, HttpRequest, HttpResponse,
5};
6use bbox_core::endpoints::abs_req_baseurl;
7use bbox_core::static_files::{embedded, embedded_index, EmbedFile};
8use bbox_core::templates::{create_env_embedded, render_endpoint};
9use minijinja::{context, Environment};
10use once_cell::sync::Lazy;
11use rust_embed::RustEmbed;
12use std::path::PathBuf;
13
14#[derive(RustEmbed)]
15#[folder = "templates/"]
16struct Templates;
17
18#[derive(RustEmbed)]
19#[folder = "static/frontend/"]
20struct FrontendStatics;
21
22static TEMPLATES: Lazy<Environment<'static>> = Lazy::new(create_env_embedded::<Templates>);
23
24async fn index(inventory: web::Data<MapInventory>) -> Result<HttpResponse, Error> {
25    let template = TEMPLATES
26        .get_template("index.html")
27        .expect("couln't load template `index.html`");
28    #[cfg(debug_assertions)]
29    let links = vec![
30        "/qgis/helloworld?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-67.593,-176.248,83.621,182.893&CRS=EPSG:4326&WIDTH=515&HEIGHT=217&LAYERS=Country,Hello&STYLES=,&FORMAT=image/png; mode=8bit&DPI=96&TRANSPARENT=TRUE",
31        "/qgis/ne?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-20037508.34278924391,-5966981.031407224014,19750246.20310878009,17477263.06060761213&CRS=EPSG:900913&WIDTH=1399&HEIGHT=824&LAYERS=country&STYLES=&FORMAT=image/png; mode=8bit",
32        "/wms/map/ne?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-20037508.34278924391,-5966981.031407224014,19750246.20310878009,17477263.06060761213&CRS=EPSG:900913&WIDTH=1399&HEIGHT=824&LAYERS=country&STYLES=&FORMAT=image/png; mode=8bit",
33        "/wms/mock/helloworld?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=-67.593,-176.248,83.621,182.893&CRS=EPSG:4326&WIDTH=515&HEIGHT=217&LAYERS=Country,Hello&STYLES=,&FORMAT=image/png; mode=8bit&DPI=96&TRANSPARENT=TRUE",
34        ];
35    #[cfg(not(debug_assertions))]
36    let links = Vec::<&str>::new();
37    let index = template
38        .render(
39            context!(cur_menu => "Home", wms_services => &inventory.wms_services, links => links),
40        )
41        .expect("index.hmtl render failed");
42    Ok(HttpResponse::Ok().content_type("text/html").body(index))
43}
44
45#[cfg(feature = "qwc2")]
46#[derive(RustEmbed)]
47#[folder = "static/qwc2/"]
48struct Qwc2Statics;
49
50#[cfg(not(feature = "qwc2"))]
51type Qwc2Statics = bbox_core::static_files::EmptyDir;
52
53async fn qwc2_map(path: web::Path<(String, PathBuf)>) -> Result<EmbedFile, Error> {
54    // Used for /qwc2_map/{theme}/index.html and /qwc2_map/{theme}/config.json
55    embedded_index::<Qwc2Statics>(path.1.clone().into()).await
56}
57
58async fn qwc2_themes(
59    inventory: web::Data<MapInventory>,
60    req: HttpRequest,
61) -> Result<HttpResponse, Error> {
62    let json = themes_json(&inventory.wms_services, abs_req_baseurl(&req), None).await;
63    Ok(HttpResponse::Ok().json(json))
64}
65
66async fn qwc2_theme(
67    id: web::Path<String>,
68    inventory: web::Data<MapInventory>,
69    req: HttpRequest,
70) -> Result<HttpResponse, Error> {
71    // let wms_service = inventory.wms_services.iter().find(|wms| wms.id == *id).unwrap().clone();
72    let json = themes_json(&inventory.wms_services, abs_req_baseurl(&req), Some(&*id)).await;
73    Ok(HttpResponse::Ok().json(json))
74}
75
76#[cfg(feature = "maplibre")]
77#[derive(RustEmbed)]
78#[folder = "static/maplibre/"]
79struct MaplibreStatics;
80
81#[cfg(not(feature = "maplibre"))]
82type MaplibreStatics = bbox_core::static_files::EmptyDir;
83
84#[cfg(feature = "openlayers")]
85#[derive(RustEmbed)]
86#[folder = "static/ol/"]
87struct OlStatics;
88
89#[cfg(not(feature = "openlayers"))]
90type OlStatics = bbox_core::static_files::EmptyDir;
91
92#[cfg(feature = "proj")]
93#[derive(RustEmbed)]
94#[folder = "static/proj/"]
95struct ProjStatics;
96
97#[cfg(not(feature = "proj"))]
98type ProjStatics = bbox_core::static_files::EmptyDir;
99
100#[cfg(feature = "swaggerui")]
101#[derive(RustEmbed)]
102#[folder = "static/swagger/"]
103struct SwaggerStatics;
104
105#[cfg(not(feature = "swaggerui"))]
106type SwaggerStatics = bbox_core::static_files::EmptyDir;
107
108async fn swaggerui_html() -> Result<HttpResponse, Error> {
109    render_endpoint(&TEMPLATES, "swaggerui.html", context!(cur_menu=>"API")).await
110}
111
112#[cfg(feature = "redoc")]
113#[derive(RustEmbed)]
114#[folder = "static/redoc/"]
115struct RedocStatics;
116
117#[cfg(not(feature = "redoc"))]
118type RedocStatics = bbox_core::static_files::EmptyDir;
119
120async fn redoc_html() -> Result<HttpResponse, Error> {
121    render_endpoint(&TEMPLATES, "redoc.html", context!(cur_menu=>"API")).await
122}
123
124async fn scalar_html() -> Result<HttpResponse, Error> {
125    render_endpoint(&TEMPLATES, "scalar.html", context!(cur_menu=>"API")).await
126}
127
128pub fn register(cfg: &mut web::ServiceConfig) {
129    cfg.service(resource("/").route(get().to(index)))
130        .service(
131            resource(r#"/frontend/{filename:.*}"#).route(get().to(embedded::<FrontendStatics>)),
132        )
133        .service(
134            resource(r#"/maplibre/{filename:.*}"#).route(get().to(embedded::<MaplibreStatics>)),
135        )
136        .service(resource(r#"/ol/{filename:.*}"#).route(get().to(embedded::<OlStatics>)))
137        .service(resource(r#"/proj/{filename:.*}"#).route(get().to(embedded::<ProjStatics>)))
138        .service(resource(r#"/swagger/{filename:.*}"#).route(get().to(embedded::<SwaggerStatics>)))
139        .service(resource("/swaggerui.html").route(get().to(swaggerui_html)))
140        .service(resource(r#"/redoc/{filename:.*}"#).route(get().to(embedded::<RedocStatics>)))
141        .service(resource("/redoc.html").route(get().to(redoc_html)))
142        .service(resource("/scalar.html").route(get().to(scalar_html)));
143    if cfg!(feature = "qwc2") {
144        cfg.service(resource("/qwc2/themes.json").route(get().to(qwc2_themes)))
145            .service(resource(r#"/qwc2/{filename:.*}"#).route(get().to(embedded::<Qwc2Statics>)))
146            .service(resource("/qwc2_map/{id}/themes.json").route(get().to(qwc2_theme)))
147            .service(resource(r#"/qwc2_map/{id}/{filename:.*}"#).route(get().to(qwc2_map)));
148    }
149    if cfg!(not(feature = "map-server")) {
150        cfg.app_data(web::Data::new(MapInventory::default()));
151    }
152}