ars_server/
context.rs

1use std::sync::Arc;
2use ahash::AHashMap;
3use ars_package::Asset;
4use bytes::Bytes;
5
6use crate::embedded_asset::EmbeddedAsset;
7use crate::config::{SrvConfig, KeycloakConfig};
8
9struct EmbeddedAssetMap {
10    inner: AHashMap<Arc<str>, EmbeddedAsset>,
11}
12
13impl EmbeddedAssetMap {
14    pub fn new(assets: &[Arc<Asset>], target_url: &str, public_url: &str, index: usize) -> anyhow::Result<Self> {
15        let mut inner = AHashMap::default();
16        for (idx, asset) in assets.iter().enumerate() {
17            if idx != index {
18                inner.insert(asset.path.clone(), EmbeddedAsset::new(asset, true, target_url, public_url)?);
19            }
20        }
21        Ok(Self {
22            inner,
23        })
24    }
25}
26
27pub type ServerConfig = SrvConfig<8000>;
28pub struct AssetStore {
29    not_found: Bytes,
30    not_found_mime: Arc<str>,
31    assets: Arc<EmbeddedAssetMap>,
32    index: EmbeddedAsset,
33    keycloak_config: EmbeddedAsset,
34}
35
36impl AssetStore {
37    pub fn new(cfg: &ServerConfig, keycloak_config: &KeycloakConfig) -> anyhow::Result<Self> {
38        let pkg_encoded = std::fs::read(cfg.asset_package())?;
39        let pkg = ars_package::deflate_decode_raw(&pkg_encoded);
40        let asset_package = ars_package::deserialize(&pkg)?;
41        let index = asset_package.assets.get(asset_package.index as usize)
42            .ok_or(anyhow::anyhow!("unable to find index.html"))?;
43
44        let target_url = &asset_package.target_url;
45        let public_url = cfg.public_url();
46        let index = EmbeddedAsset::new(index, false, target_url, public_url)?;
47        let assets = Arc::new(EmbeddedAssetMap::new(asset_package.assets.as_ref(), target_url, public_url, asset_package.index as usize)?);
48        let not_found_mime: Arc<str> = Arc::from("text/plain");
49        let not_found = Bytes::from_static(b"not found");
50        let keycloak_config = EmbeddedAsset::json(keycloak_config)?;
51        Ok(Self {
52            not_found_mime,
53            not_found,
54            assets,
55            index,
56            keycloak_config,
57        })
58    }
59
60    pub fn get(&self, id: &str) -> EmbeddedAsset {
61        self.assets
62            .inner
63            .get(id)
64            .cloned()
65            .unwrap_or_else(|| EmbeddedAsset::not_found(self.not_found.clone(), self.not_found_mime.clone()))
66    }
67
68    pub fn index(&self) -> EmbeddedAsset {
69        self.index.clone()
70    }
71
72    pub fn keycloak_config(&self) -> EmbeddedAsset {
73        self.keycloak_config.clone()
74    }
75}
76
77struct Inner {
78    config: ServerConfig,
79    store: AssetStore,    
80}
81
82#[derive(Clone)]
83pub struct App {
84    inner: Arc<Inner>,
85}
86
87impl App {
88    pub fn new() -> anyhow::Result<Self> {
89        let config = ServerConfig::from_env("SERVER_")?;
90        let keycloak_config = envy::from_env()?;
91        Ok(Self {
92            inner: Arc::new(Inner {
93                store: AssetStore::new(&config, &keycloak_config)?,
94                config,
95            })
96        })
97    }
98
99    pub fn cfg(&self) -> &ServerConfig {
100        &self.inner.config
101    }
102
103    pub fn store(&self) -> &AssetStore {
104        &self.inner.store
105    }
106}