diff --git a/beacon_node/rest_api/Cargo.toml b/beacon_node/rest_api/Cargo.toml index a3d31e410e..ac762ebb76 100644 --- a/beacon_node/rest_api/Cargo.toml +++ b/beacon_node/rest_api/Cargo.toml @@ -36,4 +36,5 @@ lighthouse_metrics = { path = "../../eth2/utils/lighthouse_metrics" } slot_clock = { path = "../../eth2/utils/slot_clock" } hex = "0.3.2" parking_lot = "0.9" +futures = "0.1.25" diff --git a/beacon_node/rest_api/src/error.rs b/beacon_node/rest_api/src/error.rs index bae07ea0b1..f3eb597a0b 100644 --- a/beacon_node/rest_api/src/error.rs +++ b/beacon_node/rest_api/src/error.rs @@ -1,15 +1,8 @@ use hyper::{Body, Method, Request, Response, Server, StatusCode}; use std::error::Error as StdError; -type Cause = Box; - -pub struct ApiError { - kind: ApiErrorKind, - cause: Option, -} - #[derive(PartialEq, Debug)] -pub enum ApiErrorKind { +pub enum ApiError { MethodNotAllowed(String), ServerError(String), NotImplemented(String), @@ -20,21 +13,27 @@ pub enum ApiErrorKind { pub type ApiResult = Result, ApiError>; -impl Into> for ApiError { - fn into(self) -> Response { - let status_code: (StatusCode, String) = match self { +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.") + .status(status_code.0) + .header("content-type", "text/plain") + .body(Body::from(*status_code.1)) + .expect("Response should always be created.") } } @@ -56,6 +55,15 @@ impl From for ApiError { } } -impl std::error::Error for ApiError { - fn cause(&self) -> Option<&Error> {} +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) + } } diff --git a/beacon_node/rest_api/src/lib.rs b/beacon_node/rest_api/src/lib.rs index 56ed8c7bb0..d7ea72cc58 100644 --- a/beacon_node/rest_api/src/lib.rs +++ b/beacon_node/rest_api/src/lib.rs @@ -14,6 +14,7 @@ mod spec; mod url_query; mod validator; +use error::{ApiError, ApiResult}; use beacon_chain::{BeaconChain, BeaconChainTypes}; use client_network::NetworkMessage; use client_network::Service as NetworkService; @@ -34,7 +35,6 @@ use url_query::UrlQuery; pub use beacon::{BlockResponse, HeadResponse, StateResponse}; pub use config::Config as ApiConfig; use eth2_libp2p::rpc::RequestId; -use serde::ser::StdError; type BoxFut = Box, Error = ApiError> + Send>; @@ -158,18 +158,19 @@ impl Service for ApiService { Ok(response) => { metrics::inc_counter(&metrics::SUCCESS_COUNT); slog::debug!(self.log, "Request successful: {:?}", path); - Box::new(response) + response } // Map the `ApiError` into `hyper::Response`. Err(e) => { slog::debug!(self.log, "Request failure: {:?}", path); - Box::new(e.into()) + e.into() } }; metrics::stop_timer(timer); Box::new(futures::future::ok(response)) + } } @@ -236,6 +237,15 @@ pub fn start_server( Ok(exit_signal) } +impl Future for ApiService { + type Item = Result, ApiError>; + type Error = ApiError; + + fn poll(&mut self) -> Result, Self::Error> { + unimplemented!() + } +} + fn success_response(body: Body) -> Response { Response::builder() .status(StatusCode::OK)