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;
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)]
pub enum SaveError {
#[error("stdio error")]

View file

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