2024-12-28 20:39:07 +11:00
|
|
|
use rocket::{get, routes, serde::json::Json, State};
|
2024-12-28 18:54:21 +11:00
|
|
|
|
2024-12-28 20:39:07 +11:00
|
|
|
pub struct ServerState {
|
2024-12-28 22:45:31 +11:00
|
|
|
primary_name: String,
|
2024-12-28 20:39:07 +11:00
|
|
|
map: std::collections::HashMap<
|
|
|
|
String,
|
|
|
|
std::sync::Arc<tokio::sync::RwLock<crate::controller::CommonData>>,
|
|
|
|
>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ServerState {
|
|
|
|
pub fn new(
|
2024-12-28 22:45:31 +11:00
|
|
|
primary_name: String,
|
2024-12-28 20:39:07 +11:00
|
|
|
map: std::collections::HashMap<
|
|
|
|
String,
|
|
|
|
std::sync::Arc<tokio::sync::RwLock<crate::controller::CommonData>>,
|
|
|
|
>,
|
|
|
|
) -> Self {
|
2024-12-28 22:45:31 +11:00
|
|
|
Self { primary_name, map }
|
2024-12-28 20:39:07 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn rocket(state: ServerState) -> rocket::Rocket<rocket::Build> {
|
2024-12-28 22:45:31 +11:00
|
|
|
rocket::build().manage(state).mount(
|
|
|
|
"/",
|
|
|
|
routes![
|
|
|
|
metrics,
|
|
|
|
interfaces,
|
|
|
|
all_interfaces,
|
|
|
|
primary_interface,
|
|
|
|
interface
|
|
|
|
],
|
|
|
|
)
|
2024-12-28 20:39:07 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/interfaces")]
|
|
|
|
fn interfaces(state: &State<ServerState>) -> Json<Vec<String>> {
|
|
|
|
Json(state.map.keys().cloned().collect())
|
|
|
|
}
|
|
|
|
|
2024-12-28 22:45:31 +11:00
|
|
|
#[get("/interfaces/primary")]
|
|
|
|
async fn primary_interface(
|
|
|
|
state: &State<ServerState>,
|
|
|
|
) -> Result<Json<crate::controller::CommonData>, ServerError> {
|
|
|
|
let s = state
|
|
|
|
.map
|
|
|
|
.get(&state.primary_name)
|
|
|
|
.ok_or(ServerError::InvalidPrimaryName)?
|
|
|
|
.read()
|
|
|
|
.await
|
|
|
|
.clone();
|
|
|
|
|
|
|
|
Ok(Json(s))
|
|
|
|
}
|
|
|
|
|
2024-12-28 20:39:07 +11:00
|
|
|
#[get("/interfaces/data")]
|
|
|
|
async fn all_interfaces(
|
|
|
|
state: &State<ServerState>,
|
|
|
|
) -> Json<Vec<(String, crate::controller::CommonData)>> {
|
|
|
|
let mut data = Vec::new();
|
|
|
|
|
|
|
|
for (k, v) in &state.map {
|
|
|
|
data.push((k.clone(), v.read().await.clone()));
|
|
|
|
}
|
|
|
|
|
|
|
|
Json(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/interface/<name>")]
|
|
|
|
async fn interface(
|
|
|
|
name: &str,
|
|
|
|
state: &State<ServerState>,
|
|
|
|
) -> Result<Json<crate::controller::CommonData>, ServerError> {
|
|
|
|
let data = state
|
|
|
|
.map
|
|
|
|
.get(name)
|
|
|
|
.ok_or(ServerError::NotFound)?
|
|
|
|
.read()
|
|
|
|
.await
|
|
|
|
.clone();
|
|
|
|
Ok(Json(data))
|
2024-12-28 18:54:21 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[get("/metrics")]
|
|
|
|
fn metrics() -> Result<String, ServerError> {
|
|
|
|
Ok(
|
|
|
|
prometheus::TextEncoder::new()
|
|
|
|
.encode_to_string(&prometheus::default_registry().gather())?,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
enum ServerError {
|
|
|
|
Prometheus,
|
2024-12-28 20:39:07 +11:00
|
|
|
NotFound,
|
2024-12-28 22:45:31 +11:00
|
|
|
InvalidPrimaryName,
|
2024-12-28 18:54:21 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<prometheus::Error> for ServerError {
|
|
|
|
fn from(_: prometheus::Error) -> Self {
|
|
|
|
Self::Prometheus
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> rocket::response::Responder<'a, 'a> for ServerError {
|
|
|
|
fn respond_to(self, _: &'a rocket::Request<'_>) -> rocket::response::Result<'a> {
|
|
|
|
Err(match self {
|
2024-12-28 22:45:31 +11:00
|
|
|
Self::Prometheus => rocket::http::Status::InternalServerError,
|
2024-12-28 20:39:07 +11:00
|
|
|
Self::NotFound => rocket::http::Status::NotFound,
|
2024-12-28 22:45:31 +11:00
|
|
|
Self::InvalidPrimaryName => rocket::http::Status::ServiceUnavailable,
|
2024-12-28 18:54:21 +11:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|