-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathmod.rs
91 lines (78 loc) · 2.69 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use std::collections::HashMap;
use std::sync::Arc;
use axum::extract::{Path, State};
use axum::routing::get;
use axum::{Json, Router};
use fedimint_core::api::InviteCode;
use fedimint_core::config::{ClientConfig, FederationId, JsonClientConfig};
use reqwest::Method;
use tower_http::cors::{Any, CorsLayer};
use tracing::warn;
use crate::config::id::fetch_federation_id;
use crate::config::meta::fetch_federation_meta;
use crate::config::modules::fetch_federation_module_kinds;
use crate::error::Result;
use crate::util::config_to_json;
use crate::AppState;
/// Helper API that exposes the federation id
pub mod id;
/// Helper API that unifies config meta and override meta, applying lenient
/// parsing
pub mod meta;
/// Helper API that exposes the federation modules
pub mod modules;
pub fn get_config_routes() -> Router<AppState> {
let router = Router::new()
.route("/:invite", get(fetch_federation_config))
.route("/:invite/meta", get(fetch_federation_meta))
.route("/:invite/id", get(fetch_federation_id))
.route("/:invite/module_kinds", get(fetch_federation_module_kinds));
let cors_enabled = dotenv::var("ALLOW_CONFIG_CORS").map_or(false, |v| v == "true");
if cors_enabled {
router.layer(
CorsLayer::new()
.allow_origin(Any)
.allow_methods([Method::GET]),
)
} else {
router
}
}
pub async fn fetch_federation_config(
Path(invite): Path<InviteCode>,
State(state): State<AppState>,
) -> Result<Json<JsonClientConfig>> {
Ok(state
.federation_config_cache
.fetch_config_cached(&invite)
.await?
.into())
}
#[derive(Default, Debug, Clone)]
pub struct FederationConfigCache {
federations: Arc<tokio::sync::RwLock<HashMap<FederationId, JsonClientConfig>>>,
}
impl FederationConfigCache {
pub async fn fetch_config_cached(
&self,
invite: &InviteCode,
) -> anyhow::Result<JsonClientConfig> {
let federation_id = invite.federation_id();
if let Some(config) = self.federations.read().await.get(&federation_id).cloned() {
return Ok(config);
}
let config = fetch_config_inner(invite).await?;
let mut cache = self.federations.write().await;
if let Some(replaced) = cache.insert(federation_id, config.clone()) {
if replaced != config {
// TODO: use tracing
warn!("Config for federation {federation_id} changed");
}
}
Ok(config)
}
}
async fn fetch_config_inner(invite: &InviteCode) -> anyhow::Result<JsonClientConfig> {
let raw_config = ClientConfig::download_from_invite_code(invite).await?;
config_to_json(raw_config)
}