bbox_asset_server/
endpoints.rs1use crate::config::AssetServiceCfg;
2use crate::qgis_plugins::*;
3use crate::runtime_templates::RuntimeTemplates;
4use crate::service::{AssetService, PluginIndex};
5use actix_files::{Files, NamedFile};
6use actix_web::{web, HttpRequest, HttpResponse, Result};
7use bbox_core::config::app_dir;
8use bbox_core::endpoints::{abs_req_baseurl, req_parent_path};
9use bbox_core::service::ServiceEndpoints;
10use log::{info, warn};
11use minijinja::context;
12use std::io::Write;
13use std::path::Path;
14use tempfile::tempfile;
15
16async fn templates(
17 envs: web::Data<RuntimeTemplates>,
18 template: web::Path<(String, String)>,
19 req: HttpRequest,
20) -> Result<HttpResponse, actix_web::Error> {
21 let path = Path::new(req.path())
22 .parent()
23 .expect("invalid req.path")
24 .parent()
25 .expect("invalid req.path")
26 .to_str()
27 .expect("invalid req.path")
28 .to_string();
29 let (stem, param) = template.into_inner();
30 let name = format!("{stem}.html");
31 let env = envs.get(&path).unwrap();
32 let tmpl = env.get_template(&name).unwrap();
33 let out = tmpl
34 .render(context!(param => param))
35 .expect("Template render failed");
36 Ok(HttpResponse::Ok().content_type("text/html").body(out))
37}
38
39async fn plugin_xml(plugins_index: web::Data<PluginIndex>, req: HttpRequest) -> Result<NamedFile> {
40 let url = format!("{}/plugins{}", abs_req_baseurl(&req), req_parent_path(&req));
42 let zips = plugins_index
43 .get(req.path())
44 .expect("zip file list missing");
45 let plugins = plugin_metadata(zips);
46 let xml = render_plugin_xml(&plugins, &url);
47 let mut file = tempfile()?;
48 file.write_all(xml.as_bytes())?;
49 Ok(NamedFile::from_file(file, "plugin.xml")?)
50}
51
52impl ServiceEndpoints for AssetService {
53 fn register_endpoints(&self, cfg: &mut web::ServiceConfig) {
54 let service_cfg = AssetServiceCfg::from_config();
55
56 for static_dir in &service_cfg.static_ {
57 let dir = app_dir(&static_dir.dir);
58 if dir.is_dir() {
59 info!(
60 "Serving static files from directory '{}' on '{}'",
61 dir.display(),
62 &static_dir.path
63 );
64 cfg.service(Files::new(&static_dir.path, &dir));
65 } else {
66 warn!("Static file directory '{}' not found", dir.display(),);
67 }
68 }
69
70 let mut template_envs = RuntimeTemplates::default();
71 for template_dir in &service_cfg.template {
72 let dir = app_dir(&template_dir.dir).to_string_lossy().to_string();
73 if Path::new(&dir).is_dir() {
74 let dest = &template_dir.path;
75 info!("Serving template files from directory '{dir}' on '{dest}'");
76 template_envs.add(&dir, dest);
77 cfg.route(
78 &format!("{dest}/{{name}}/{{param}}"),
79 web::get().to(templates),
80 );
81 } else {
82 warn!("Template file directory '{dir}' not found");
83 }
84 }
85 cfg.app_data(web::Data::new(template_envs));
86
87 cfg.app_data(web::Data::new(self.plugins_index.clone()));
88
89 for repo in &service_cfg.repo {
90 let dir = app_dir(&repo.dir);
91 if dir.is_dir() {
92 let xmldir = format!("{}/plugins.xml", repo.path);
93 info!(
94 "Serving QGIS plugin repository from directory '{}' on '{xmldir}'",
95 dir.display()
96 );
97 cfg.service(Files::new(
98 &format!("{}/static", repo.path),
99 app_dir("bbox-asset-server/src/static"), ))
101 .route(&xmldir, web::get().to(plugin_xml))
102 .service(Files::new(&format!("/plugins{}", repo.path), &dir));
104 } else {
105 }
107 }
108 }
109}