niom-webrtc/src/config.rs

114 lines
3.6 KiB
Rust

use serde::Deserialize;
use std::path::Path;
#[derive(Debug, Deserialize, Clone)]
pub struct ServerOptions {
pub stun_server: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
pub server: ServerOptions,
}
impl Config {
pub fn from_file<P: AsRef<Path>>(p: P) -> Result<Self, Box<dyn std::error::Error>> {
let s = std::fs::read_to_string(p)?;
let cfg: Config = serde_json::from_str(&s)?;
Ok(cfg)
}
pub fn load_default() -> Result<Self, Box<dyn std::error::Error>> {
Self::from_file("appsettings.json")
}
}
// WASM runtime loader: fetch `appsettings.json` from the hosting origin
#[cfg(target_arch = "wasm32")]
pub async fn load_config_from_server() -> Result<Config, Box<dyn std::error::Error>> {
// First try HTML-injection fast-path: look for a <script id="app-config"> element
if let Ok(Some(cfg)) = load_config_from_html().await {
return Ok(cfg);
}
// Fallback to fetching appsettings.json from the hosting origin
let resp = gloo_net::http::Request::get("appsettings.json").send().await?;
let text = resp.text().await?;
let cfg: Config = serde_json::from_str(&text)?;
Ok(cfg)
}
// Try to read a JSON config injected into index.html inside a script tag
#[cfg(target_arch = "wasm32")]
async fn load_config_from_html() -> Result<Option<Config>, Box<dyn std::error::Error>> {
use wasm_bindgen::JsCast;
use web_sys::window;
let win = window().ok_or("no window")?;
let doc = win.document().ok_or("no document")?;
if let Some(elem) = doc.get_element_by_id("app-config") {
if let Some(text) = elem.text_content() {
let cfg: Config = serde_json::from_str(&text)?;
return Ok(Some(cfg));
}
}
Ok(None)
}
// Synchronous HTML fast-path for WASM: read script#app-config synchronously if present.
#[cfg(target_arch = "wasm32")]
pub fn load_config_from_html_sync() -> Option<Config> {
use wasm_bindgen::JsCast;
use web_sys::window;
let win = window().ok()?;
let doc = win.document()?;
let elem = doc.get_element_by_id("app-config")?;
if let Some(text) = elem.text_content() {
if let Ok(cfg) = serde_json::from_str::<Config>(&text) {
return Some(cfg);
}
}
None
}
/// Synchronous loader that prefers the HTML-injection fast-path on WASM, otherwise reads file on native.
pub fn load_config_sync_or_default() -> Config {
// WASM: try HTML-injection first
#[cfg(target_arch = "wasm32")]
{
if let Some(cfg) = load_config_from_html_sync() {
return cfg;
}
}
// Native: try reading appsettings.json from file
#[cfg(not(target_arch = "wasm32"))]
{
if let Ok(cfg) = Config::from_file("appsettings.json") {
return cfg;
}
}
// Fallback default
Config { server: ServerOptions { stun_server: crate::constants::DEFAULT_STUN_SERVER.to_string() } }
}
// Native loader convenience wrapper (blocking-friendly)
#[cfg(not(target_arch = "wasm32"))]
pub async fn load_config_from_server() -> Result<Config, Box<dyn std::error::Error>> {
// On native we can just read the file synchronously and return
Ok(Config::from_file("appsettings.json")?)
}
/// High-level loader with fallbacks: try wasm fetch (or native read), otherwise fallback to defaults.
pub async fn load_config_or_default() -> Config {
// Try to load via the async loader
if let Ok(cfg) = load_config_from_server().await {
return cfg;
}
// Fallback default
Config { server: ServerOptions { stun_server: crate::constants::DEFAULT_STUN_SERVER.to_string() } }
}