use hyper::{Body, Method, Request, Response, Server, StatusCode}; use std::error::Error as StdError; #[derive(PartialEq, Debug)] pub enum ApiError { MethodNotAllowed(String), ServerError(String), NotImplemented(String), InvalidQueryParams(String), NotFound(String), ImATeapot(String), // Just in case. } pub type ApiResult = Result, ApiError>; impl ApiError { pub fn status_code(&self) -> (StatusCode, &String) { match self { ApiError::MethodNotAllowed(desc) => (StatusCode::METHOD_NOT_ALLOWED, desc), ApiError::ServerError(desc) => (StatusCode::INTERNAL_SERVER_ERROR, desc), ApiError::NotImplemented(desc) => (StatusCode::NOT_IMPLEMENTED, desc), ApiError::InvalidQueryParams(desc) => (StatusCode::BAD_REQUEST, desc), ApiError::NotFound(desc) => (StatusCode::NOT_FOUND, desc), ApiError::ImATeapot(desc) => (StatusCode::IM_A_TEAPOT, desc), } } } impl Into> for ApiError { fn into(self) -> Response { let status_code = self.status_code(); Response::builder() .status(status_code.0) .header("content-type", "text/plain") .body(Body::from(*status_code.1)) .expect("Response should always be created.") } } impl From for ApiError { fn from(e: store::Error) -> ApiError { ApiError::ServerError(format!("Database error: {:?}", e)) } } impl From for ApiError { fn from(e: types::BeaconStateError) -> ApiError { ApiError::ServerError(format!("BeaconState error: {:?}", e)) } } impl From for ApiError { fn from(e: state_processing::per_slot_processing::Error) -> ApiError { ApiError::ServerError(format!("PerSlotProcessing error: {:?}", e)) } } impl StdError for ApiError { fn cause(&self) -> Option<&StdError> { None } } impl std::fmt::Display for ApiError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let status = self.status_code(); write!(f, "{:?}: {:?}", status.0, status.1) } }