2019-09-10 14:40:22 +00:00
|
|
|
use crate::BoxFut;
|
2019-09-13 09:38:40 +00:00
|
|
|
use hyper::{Body, Response, StatusCode};
|
2019-09-10 00:56:50 +00:00
|
|
|
use std::error::Error as StdError;
|
|
|
|
|
2019-09-10 09:30:36 +00:00
|
|
|
#[derive(PartialEq, Debug, Clone)]
|
2019-09-10 05:35:54 +00:00
|
|
|
pub enum ApiError {
|
2019-09-10 00:56:50 +00:00
|
|
|
MethodNotAllowed(String),
|
|
|
|
ServerError(String),
|
|
|
|
NotImplemented(String),
|
|
|
|
InvalidQueryParams(String),
|
|
|
|
NotFound(String),
|
2019-09-13 10:42:56 +00:00
|
|
|
UnsupportedType(String),
|
2019-09-10 00:56:50 +00:00
|
|
|
ImATeapot(String), // Just in case.
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type ApiResult = Result<Response<Body>, ApiError>;
|
|
|
|
|
2019-09-10 05:35:54 +00:00
|
|
|
impl ApiError {
|
2019-09-10 09:30:36 +00:00
|
|
|
pub fn status_code(self) -> (StatusCode, String) {
|
2019-09-10 05:35:54 +00:00
|
|
|
match self {
|
2019-09-10 00:56:50 +00:00
|
|
|
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),
|
2019-09-13 10:42:56 +00:00
|
|
|
ApiError::UnsupportedType(desc) => (StatusCode::UNSUPPORTED_MEDIA_TYPE, desc),
|
2019-09-10 00:56:50 +00:00
|
|
|
ApiError::ImATeapot(desc) => (StatusCode::IM_A_TEAPOT, desc),
|
2019-09-10 05:35:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Into<Response<Body>> for ApiError {
|
|
|
|
fn into(self) -> Response<Body> {
|
|
|
|
let status_code = self.status_code();
|
2019-09-10 00:56:50 +00:00
|
|
|
Response::builder()
|
2019-09-10 09:30:36 +00:00
|
|
|
.status(status_code.0)
|
|
|
|
.header("content-type", "text/plain")
|
|
|
|
.body(Body::from(status_code.1))
|
|
|
|
.expect("Response should always be created.")
|
2019-09-10 00:56:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:40:22 +00:00
|
|
|
impl Into<BoxFut> for ApiError {
|
|
|
|
fn into(self) -> BoxFut {
|
|
|
|
Box::new(futures::future::err(self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 00:56:50 +00:00
|
|
|
impl From<store::Error> for ApiError {
|
|
|
|
fn from(e: store::Error) -> ApiError {
|
|
|
|
ApiError::ServerError(format!("Database error: {:?}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<types::BeaconStateError> for ApiError {
|
|
|
|
fn from(e: types::BeaconStateError) -> ApiError {
|
|
|
|
ApiError::ServerError(format!("BeaconState error: {:?}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<state_processing::per_slot_processing::Error> for ApiError {
|
|
|
|
fn from(e: state_processing::per_slot_processing::Error) -> ApiError {
|
|
|
|
ApiError::ServerError(format!("PerSlotProcessing error: {:?}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 14:40:22 +00:00
|
|
|
impl From<hyper::error::Error> for ApiError {
|
|
|
|
fn from(e: hyper::error::Error) -> ApiError {
|
|
|
|
ApiError::ServerError(format!("Networking error: {:?}", e))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 05:35:54 +00:00
|
|
|
impl StdError for ApiError {
|
2019-09-13 09:38:40 +00:00
|
|
|
fn cause(&self) -> Option<&dyn StdError> {
|
2019-09-10 05:35:54 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Display for ApiError {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
2019-09-10 09:30:36 +00:00
|
|
|
let status = self.clone().status_code();
|
2019-09-10 05:35:54 +00:00
|
|
|
write!(f, "{:?}: {:?}", status.0, status.1)
|
|
|
|
}
|
2019-09-10 00:56:50 +00:00
|
|
|
}
|