http error codes

This commit is contained in:
Alex Janka 2024-01-12 10:12:15 +11:00
parent 4dc8b065b0
commit e1c6759e85
2 changed files with 63 additions and 13 deletions

View file

@ -1,3 +1,6 @@
use std::sync::PoisonError;
use rocket::response::Responder;
use thiserror::Error; use thiserror::Error;
pub trait PrintErrors { pub trait PrintErrors {
@ -22,6 +25,34 @@ where
} }
} }
#[derive(Error, Debug)]
pub enum ServerError {
#[error("rwlock error")]
// 500
Lock,
#[error("no data")]
// 503
NoData,
#[error("prometheus")]
Prometheus(#[from] prometheus::Error),
}
impl<T> From<PoisonError<T>> for ServerError {
fn from(_: PoisonError<T>) -> Self {
Self::Lock
}
}
impl<'a> Responder<'a, 'a> for ServerError {
fn respond_to(self, _: &'a rocket::Request<'_>) -> rocket::response::Result<'a> {
Err(match self {
ServerError::Lock => rocket::http::Status::InternalServerError,
ServerError::NoData => rocket::http::Status::ServiceUnavailable,
ServerError::Prometheus(_) => rocket::http::Status::InternalServerError,
})
}
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum SaveError { pub enum SaveError {
#[error("stdio error")] #[error("stdio error")]

View file

@ -11,6 +11,7 @@ use rocket::{
use crate::{ use crate::{
api_interface::InterfaceRequest, api_interface::InterfaceRequest,
config::Config, config::Config,
errors::ServerError,
pl_interface::{PlState, PliRequest}, pl_interface::{PlState, PliRequest},
types::{CarState, ChargeState, ClimateState}, types::{CarState, ChargeState, ClimateState},
}; };
@ -63,19 +64,35 @@ fn rocket(state: ServerState) -> rocket::Rocket<rocket::Build> {
} }
#[get("/home")] #[get("/home")]
async fn home(state: &State<ServerState>) -> Option<Json<bool>> { async fn home(state: &State<ServerState>) -> Result<Json<bool>, ServerError> {
let location_data = &state.car_state.read().ok()?.location_data?; let location_data = &state
Some(Json(location_data.coords.overlaps(&state.config.coords))) .car_state
.read()?
.location_data
.ok_or(ServerError::NoData)?;
Ok(Json(location_data.coords.overlaps(&state.config.coords)))
} }
#[get("/charge-state")] #[get("/charge-state")]
async fn charge_state(state: &State<ServerState>) -> Option<Json<ChargeState>> { async fn charge_state(state: &State<ServerState>) -> Result<Json<ChargeState>, ServerError> {
Some(Json(state.car_state.read().ok()?.charge_state?)) Ok(Json(
state
.car_state
.read()?
.charge_state
.ok_or(ServerError::NoData)?,
))
} }
#[get("/climate-state")] #[get("/climate-state")]
async fn climate_state(state: &State<ServerState>) -> Option<Json<ClimateState>> { async fn climate_state(state: &State<ServerState>) -> Result<Json<ClimateState>, ServerError> {
Some(Json(state.car_state.read().ok()?.climate_state?)) Ok(Json(
state
.car_state
.read()?
.climate_state
.ok_or(ServerError::NoData)?,
))
} }
#[post("/flash")] #[post("/flash")]
@ -84,10 +101,11 @@ async fn flash(state: &State<ServerState>) {
} }
#[get("/metrics")] #[get("/metrics")]
fn metrics() -> Option<String> { fn metrics() -> Result<String, ServerError> {
Ok(
prometheus::TextEncoder::new() prometheus::TextEncoder::new()
.encode_to_string(&prometheus::default_registry().gather()) .encode_to_string(&prometheus::default_registry().gather())?,
.ok() )
} }
#[get("/read-ram/<address>")] #[get("/read-ram/<address>")]
@ -97,11 +115,12 @@ async fn read_ram(address: u8, state: &State<ServerState>) -> String {
} }
#[get("/regulator-state")] #[get("/regulator-state")]
async fn regulator_state(state: &State<ServerState>) -> Option<Json<PlState>> { async fn regulator_state(state: &State<ServerState>) -> Result<Json<PlState>, ServerError> {
state state
.pl_state .pl_state
.as_ref() .as_ref()
.and_then(|v| Some(Json(*(v.read().ok()?)))) .ok_or(ServerError::NoData)
.and_then(|v| Ok(Json(*(v.read()?))))
} }
pub struct Cors; pub struct Cors;