Cleaning up the rest of the API functions.

- Removed all unused imports
 - Fixed random compiler errors
 - Removed all of the 'sucess_response' helpers.
 - Enabled all of the API endpoints again, wrapping in 'into_boxfut'
 - Tidied up /metrics endpoint
 - Added a 'body_text' part to ResponseBuilder, mainly for the Prometheus /metrics endpoint
 - Cleaned up the unnecessary helpers::* imports, to be more explicit.
This commit is contained in:
Luke Anderson 2019-09-13 19:38:40 +10:00
parent 006350c0cd
commit 1dd86baf1a
No known key found for this signature in database
GPG Key ID: 44408169EC61E228
10 changed files with 70 additions and 108 deletions

View File

@ -1,6 +1,6 @@
use crate::helpers::*; use crate::helpers::*;
use crate::response_builder::ResponseBuilder; use crate::response_builder::ResponseBuilder;
use crate::{ApiError, ApiResult, BoxFut, NetworkService, UrlQuery}; use crate::{ApiError, ApiResult, UrlQuery};
use beacon_chain::{BeaconChain, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainTypes};
use hyper::{Body, Request}; use hyper::{Body, Request};
use serde::Serialize; use serde::Serialize;

View File

@ -1,7 +1,5 @@
use crate::BoxFut; use crate::BoxFut;
use futures::future::IntoFuture; use hyper::{Body, Response, StatusCode};
use futures::Future;
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use std::error::Error as StdError; use std::error::Error as StdError;
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]
@ -71,7 +69,7 @@ impl From<hyper::error::Error> for ApiError {
} }
impl StdError for ApiError { impl StdError for ApiError {
fn cause(&self) -> Option<&StdError> { fn cause(&self) -> Option<&dyn StdError> {
None None
} }
} }

View File

@ -1,53 +1,19 @@
use crate::response_builder::ResponseBuilder; use crate::{ApiError, ApiResult};
use crate::{ApiError, ApiResult, BoxFut};
use beacon_chain::{BeaconChain, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainTypes};
use bls::PublicKey; use bls::PublicKey;
use eth2_libp2p::{PubsubMessage, Topic}; use eth2_libp2p::{PubsubMessage, Topic};
use eth2_libp2p::{BEACON_BLOCK_TOPIC, TOPIC_ENCODING_POSTFIX, TOPIC_PREFIX}; use eth2_libp2p::{BEACON_BLOCK_TOPIC, TOPIC_ENCODING_POSTFIX, TOPIC_PREFIX};
use hex; use hex;
use http::header; use http::header;
use hyper::{Body, Request, Response, StatusCode}; use hyper::{Body, Request};
use network::NetworkMessage; use network::NetworkMessage;
use parking_lot::RwLock; use parking_lot::RwLock;
use serde::Serialize;
use ssz::Encode; use ssz::Encode;
use std::sync::Arc; use std::sync::Arc;
use store::{iter::AncestorIter, Store}; use store::{iter::AncestorIter, Store};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use types::{BeaconBlock, BeaconState, EthSpec, Hash256, RelativeEpoch, Slot}; use types::{BeaconBlock, BeaconState, EthSpec, Hash256, RelativeEpoch, Slot};
pub fn success_response<T: Serialize + Encode>(req: Request<Body>, item: &T) -> BoxFut {
Box::new(match ResponseBuilder::new(&req).body(item) {
Ok(resp) => futures::future::ok(resp),
Err(e) => futures::future::err(e),
})
}
pub fn success_response_2<T: Serialize + Encode>(req: Request<Body>, item: &T) -> ApiResult {
ResponseBuilder::new(&req).body(item)
}
pub fn success_response_2_json<T: Serialize>(req: Request<Body>, item: &T) -> ApiResult {
ResponseBuilder::new(&req).body_json(item)
}
pub fn success_response_json<T: Serialize>(req: Request<Body>, item: &T) -> BoxFut {
if let Err(e) = check_content_type_for_json(&req) {
return Box::new(futures::future::err(e));
}
Box::new(match ResponseBuilder::new(&req).body_json(item) {
Ok(resp) => futures::future::ok(resp),
Err(e) => futures::future::err(e),
})
}
pub fn success_response_old(body: Body) -> Response<Body> {
Response::builder()
.status(StatusCode::OK)
.header("content-type", "application/json")
.body(body)
.expect("We should always be able to make response from the success body.")
}
/// Parse a slot from a `0x` preixed string. /// Parse a slot from a `0x` preixed string.
/// ///
/// E.g., `"1234"` /// E.g., `"1234"`

View File

@ -23,9 +23,8 @@ use error::{ApiError, ApiResult};
use eth2_config::Eth2Config; use eth2_config::Eth2Config;
use futures::future::IntoFuture; use futures::future::IntoFuture;
use hyper::rt::Future; use hyper::rt::Future;
use hyper::server::conn::AddrStream; use hyper::service::Service;
use hyper::service::{MakeService, Service}; use hyper::{Body, Method, Request, Response, Server};
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use parking_lot::RwLock; use parking_lot::RwLock;
use slog::{info, o, warn}; use slog::{info, o, warn};
use std::ops::Deref; use std::ops::Deref;
@ -37,8 +36,6 @@ use url_query::UrlQuery;
pub use beacon::{BlockResponse, HeadResponse, StateResponse}; pub use beacon::{BlockResponse, HeadResponse, StateResponse};
pub use config::Config as ApiConfig; pub use config::Config as ApiConfig;
use eth2_libp2p::rpc::RequestId;
use serde::export::PhantomData;
type BoxFut = Box<dyn Future<Item = Response<Body>, Error = ApiError> + Send>; type BoxFut = Box<dyn Future<Item = Response<Body>, Error = ApiError> + Send>;
@ -107,58 +104,66 @@ impl<T: BeaconChainTypes> Service for ApiService<T> {
(&Method::GET, "/network/listen_addresses") => { (&Method::GET, "/network/listen_addresses") => {
into_boxfut(network::get_listen_addresses::<T>(req)) into_boxfut(network::get_listen_addresses::<T>(req))
} }
/*
// Methods for Beacon Node // Methods for Beacon Node
(&Method::GET, "/beacon/head") => beacon::get_head::<T>(req), (&Method::GET, "/beacon/head") => into_boxfut(beacon::get_head::<T>(req)),
(&Method::GET, "/beacon/block") => beacon::get_block::<T>(req), (&Method::GET, "/beacon/block") => into_boxfut(beacon::get_block::<T>(req)),
(&Method::GET, "/beacon/block_root") => beacon::get_block_root::<T>(req), (&Method::GET, "/beacon/block_root") => into_boxfut(beacon::get_block_root::<T>(req)),
(&Method::GET, "/beacon/blocks") => helpers::implementation_pending_response(req), (&Method::GET, "/beacon/blocks") => {
(&Method::GET, "/beacon/fork") => beacon::get_fork::<T>(req), into_boxfut(helpers::implementation_pending_response(req))
(&Method::GET, "/beacon/attestations") => helpers::implementation_pending_response(req), }
(&Method::GET, "/beacon/fork") => into_boxfut(beacon::get_fork::<T>(req)),
(&Method::GET, "/beacon/attestations") => {
into_boxfut(helpers::implementation_pending_response(req))
}
(&Method::GET, "/beacon/attestations/pending") => { (&Method::GET, "/beacon/attestations/pending") => {
helpers::implementation_pending_response(req) into_boxfut(helpers::implementation_pending_response(req))
} }
(&Method::GET, "/beacon/validators") => beacon::get_validators::<T>(req), (&Method::GET, "/beacon/validators") => into_boxfut(beacon::get_validators::<T>(req)),
(&Method::GET, "/beacon/validators/indicies") => { (&Method::GET, "/beacon/validators/indicies") => {
helpers::implementation_pending_response(req) into_boxfut(helpers::implementation_pending_response(req))
} }
(&Method::GET, "/beacon/validators/pubkeys") => { (&Method::GET, "/beacon/validators/pubkeys") => {
helpers::implementation_pending_response(req) into_boxfut(helpers::implementation_pending_response(req))
} }
// Methods for Validator // Methods for Validator
(&Method::GET, "/beacon/validator/duties") => validator::get_validator_duties::<T>(req), (&Method::GET, "/beacon/validator/duties") => {
(&Method::GET, "/beacon/validator/block") => validator::get_new_beacon_block::<T>(req), into_boxfut(validator::get_validator_duties::<T>(req))
*/ }
(&Method::GET, "/beacon/validator/block") => {
into_boxfut(validator::get_new_beacon_block::<T>(req))
}
(&Method::POST, "/beacon/validator/block") => validator::publish_beacon_block::<T>(req), (&Method::POST, "/beacon/validator/block") => validator::publish_beacon_block::<T>(req),
/*
(&Method::GET, "/beacon/validator/attestation") => { (&Method::GET, "/beacon/validator/attestation") => {
validator::get_new_attestation::<T>(req) into_boxfut(validator::get_new_attestation::<T>(req))
} }
(&Method::POST, "/beacon/validator/attestation") => { (&Method::POST, "/beacon/validator/attestation") => {
helpers::implementation_pending_response(req) into_boxfut(helpers::implementation_pending_response(req))
} }
(&Method::GET, "/beacon/state") => beacon::get_state::<T>(req), (&Method::GET, "/beacon/state") => into_boxfut(beacon::get_state::<T>(req)),
(&Method::GET, "/beacon/state_root") => beacon::get_state_root::<T>(req), (&Method::GET, "/beacon/state_root") => into_boxfut(beacon::get_state_root::<T>(req)),
(&Method::GET, "/beacon/state/current_finalized_checkpoint") => { (&Method::GET, "/beacon/state/current_finalized_checkpoint") => {
beacon::get_current_finalized_checkpoint::<T>(req) into_boxfut(beacon::get_current_finalized_checkpoint::<T>(req))
}
(&Method::GET, "/beacon/state/genesis") => {
into_boxfut(beacon::get_genesis_state::<T>(req))
} }
(&Method::GET, "/beacon/state/genesis") => beacon::get_genesis_state::<T>(req),
//TODO: Add aggreggate/filtered state lookups here, e.g. /beacon/validators/balances //TODO: Add aggreggate/filtered state lookups here, e.g. /beacon/validators/balances
// Methods for bootstrap and checking configuration // Methods for bootstrap and checking configuration
(&Method::GET, "/spec") => spec::get_spec::<T>(req), (&Method::GET, "/spec") => into_boxfut(spec::get_spec::<T>(req)),
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req), (&Method::GET, "/spec/slots_per_epoch") => {
(&Method::GET, "/spec/deposit_contract") => { into_boxfut(spec::get_slots_per_epoch::<T>(req))
helpers::implementation_pending_response(req)
} }
(&Method::GET, "/spec/eth2_config") => spec::get_eth2_config::<T>(req), (&Method::GET, "/spec/deposit_contract") => {
into_boxfut(helpers::implementation_pending_response(req))
}
(&Method::GET, "/spec/eth2_config") => into_boxfut(spec::get_eth2_config::<T>(req)),
(&Method::GET, "/metrics") => metrics::get_prometheus::<T>(req), (&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(req)),
*/
_ => Box::new(futures::future::err(ApiError::NotFound( _ => Box::new(futures::future::err(ApiError::NotFound(
"Request path and/or method not found.".to_owned(), "Request path and/or method not found.".to_owned(),
))), ))),

View File

@ -1,7 +1,7 @@
use crate::helpers::get_beacon_chain_from_request;
use crate::response_builder::ResponseBuilder; use crate::response_builder::ResponseBuilder;
use crate::{helpers::*, ApiError, ApiResult, DBPath}; use crate::{ApiError, ApiResult, DBPath};
use beacon_chain::BeaconChainTypes; use beacon_chain::BeaconChainTypes;
use http::HeaderValue;
use hyper::{Body, Request}; use hyper::{Body, Request};
use prometheus::{Encoder, TextEncoder}; use prometheus::{Encoder, TextEncoder};
@ -62,14 +62,6 @@ pub fn get_prometheus<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiR
.unwrap(); .unwrap();
String::from_utf8(buffer) String::from_utf8(buffer)
.map(|string| { .map(|string| ResponseBuilder::new(&req).body_text(string))
let mut response = success_response_old(Body::from(string)); .map_err(|e| ApiError::ServerError(format!("Failed to encode prometheus info: {:?}", e)))?
// Need to change the header to text/plain for prometheus
response.headers_mut().insert(
"content-type",
HeaderValue::from_static("text/plain; charset=utf-8"),
);
response
})
.map_err(|e| ApiError::ServerError(format!("Failed to encode prometheus info: {:?}", e)))
} }

View File

@ -1,9 +1,8 @@
use crate::error::{ApiError, ApiResult}; use crate::error::ApiResult;
use crate::helpers::*;
use crate::response_builder::ResponseBuilder; use crate::response_builder::ResponseBuilder;
use crate::NetworkService; use crate::NetworkService;
use beacon_chain::BeaconChainTypes; use beacon_chain::BeaconChainTypes;
use eth2_libp2p::{Enr, Multiaddr, PeerId}; use eth2_libp2p::{Multiaddr, PeerId};
use hyper::{Body, Request}; use hyper::{Body, Request};
use std::sync::Arc; use std::sync::Arc;

View File

@ -1,6 +1,6 @@
use crate::helpers::*; use crate::helpers::get_beacon_chain_from_request;
use crate::response_builder::ResponseBuilder; use crate::response_builder::ResponseBuilder;
use crate::{ApiResult, BoxFut}; use crate::ApiResult;
use beacon_chain::BeaconChainTypes; use beacon_chain::BeaconChainTypes;
use hyper::{Body, Request}; use hyper::{Body, Request};
use version; use version;

View File

@ -61,4 +61,12 @@ impl ResponseBuilder {
})?)) })?))
.map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e))) .map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e)))
} }
pub fn body_text(self, text: String) -> ApiResult {
Response::builder()
.status(StatusCode::OK)
.header("content-type", "text/plain; charset=utf-8")
.body(Body::from(text))
.map_err(|e| ApiError::ServerError(format!("Failed to build response: {:?}", e)))
}
} }

View File

@ -1,5 +1,6 @@
use super::ApiResult; use super::ApiResult;
use crate::helpers::*; use crate::helpers::get_beacon_chain_from_request;
use crate::response_builder::ResponseBuilder;
use crate::ApiError; use crate::ApiError;
use beacon_chain::BeaconChainTypes; use beacon_chain::BeaconChainTypes;
use eth2_config::Eth2Config; use eth2_config::Eth2Config;
@ -10,11 +11,7 @@ use types::EthSpec;
/// HTTP handler to return the full spec object. /// HTTP handler to return the full spec object.
pub fn get_spec<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult { pub fn get_spec<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
let beacon_chain = get_beacon_chain_from_request::<T>(&req)?; let beacon_chain = get_beacon_chain_from_request::<T>(&req)?;
ResponseBuilder::new(&req).body_json(&beacon_chain.spec)
let json: String = serde_json::to_string(&beacon_chain.spec)
.map_err(|e| ApiError::ServerError(format!("Unable to serialize spec: {:?}", e)))?;
Ok(success_response_old(Body::from(json)))
} }
/// HTTP handler to return the full Eth2Config object. /// HTTP handler to return the full Eth2Config object.
@ -24,16 +21,10 @@ pub fn get_eth2_config<T: BeaconChainTypes + 'static>(req: Request<Body>) -> Api
.get::<Arc<Eth2Config>>() .get::<Arc<Eth2Config>>()
.ok_or_else(|| ApiError::ServerError("Eth2Config extension missing".to_string()))?; .ok_or_else(|| ApiError::ServerError("Eth2Config extension missing".to_string()))?;
let json: String = serde_json::to_string(eth2_config.as_ref()) ResponseBuilder::new(&req).body_json(eth2_config.as_ref())
.map_err(|e| ApiError::ServerError(format!("Unable to serialize Eth2Config: {:?}", e)))?;
Ok(success_response_old(Body::from(json)))
} }
/// HTTP handler to return the full spec object. /// HTTP handler to return the full spec object.
pub fn get_slots_per_epoch<T: BeaconChainTypes + 'static>(_req: Request<Body>) -> ApiResult { pub fn get_slots_per_epoch<T: BeaconChainTypes + 'static>(req: Request<Body>) -> ApiResult {
let json: String = serde_json::to_string(&T::EthSpec::slots_per_epoch()) ResponseBuilder::new(&req).body(&T::EthSpec::slots_per_epoch())
.map_err(|e| ApiError::ServerError(format!("Unable to serialize epoch: {:?}", e)))?;
Ok(success_response_old(Body::from(json)))
} }

View File

@ -1,11 +1,14 @@
use crate::helpers::*; use crate::helpers::{
check_content_type_for_json, get_beacon_chain_from_request, get_logger_from_request,
parse_pubkey, publish_beacon_block_to_network,
};
use crate::response_builder::ResponseBuilder; use crate::response_builder::ResponseBuilder;
use crate::{ApiError, ApiResult, BoxFut, UrlQuery}; use crate::{ApiError, ApiResult, BoxFut, UrlQuery};
use beacon_chain::{BeaconChainTypes, BlockProcessingOutcome}; use beacon_chain::{BeaconChainTypes, BlockProcessingOutcome};
use bls::{AggregateSignature, PublicKey, Signature}; use bls::{AggregateSignature, PublicKey, Signature};
use futures::future::Future; use futures::future::Future;
use futures::stream::Stream; use futures::stream::Stream;
use hyper::{Body, Error, Request}; use hyper::{Body, Request};
use network::NetworkMessage; use network::NetworkMessage;
use parking_lot::RwLock; use parking_lot::RwLock;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};