Made async functions work!

- Cleaned up imports
 - Moved ApiError and such to it's own error.rs
 - Obsoleted 'success_response' in favour of new async regular and json only flavours
 - Made ApiError work async and be derived from hyper errors
 - Added a check to ensure an error is thrown if a non-json encoding is requested on a json-only function
 - Made all the individual service functions return futures (only node and network for now)
This commit is contained in:
Luke Anderson
2019-09-11 00:40:22 +10:00
parent b0090df543
commit b8667217f0
10 changed files with 143 additions and 138 deletions

View File

@@ -1,19 +1,46 @@
use crate::{ApiError, ApiResult};
use crate::response_builder::ResponseBuilder;
use crate::{ApiError, ApiResult, BoxFut};
use beacon_chain::{BeaconChain, BeaconChainTypes};
use bls::PublicKey;
use eth2_libp2p::{PubsubMessage, Topic};
use eth2_libp2p::{BEACON_BLOCK_TOPIC, TOPIC_ENCODING_POSTFIX, TOPIC_PREFIX};
use hex;
use http::header;
use hyper::{Body, Request};
use hyper::{Body, Request, Response, StatusCode};
use network::NetworkMessage;
use parking_lot::RwLock;
use serde::Serialize;
use ssz::Encode;
use std::sync::Arc;
use store::{iter::AncestorIter, Store};
use tokio::sync::mpsc;
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_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.
///
/// E.g., `"1234"`
@@ -24,6 +51,21 @@ pub fn parse_slot(string: &str) -> Result<Slot, ApiError> {
.map_err(|e| ApiError::InvalidQueryParams(format!("Unable to parse slot: {:?}", e)))
}
/// Checks the provided request to ensure that the `content-type` header.
///
/// The content-type header should either be omitted, in which case JSON is assumed, or it should
/// explicity specify `application/json`. If anything else is provided, an error is returned.
pub fn check_content_type_for_json(req: &Request<Body>) -> Result<(), ApiError> {
match req.headers().get(header::CONTENT_TYPE) {
Some(h) if h == "application/json" => Ok(()),
Some(h) => Err(ApiError::InvalidQueryParams(format!(
"The provided content-type {:?} is not available, this endpoint only supports json.",
h
))),
_ => Ok(()),
}
}
/// Parse a root from a `0x` preixed string.
///
/// E.g., `"0x0000000000000000000000000000000000000000000000000000000000000000"`
@@ -42,21 +84,6 @@ pub fn parse_root(string: &str) -> Result<Hash256, ApiError> {
}
}
/// Checks the provided request to ensure that the `content-type` header.
///
/// The content-type header should either be omitted, in which case JSON is assumed, or it should
/// explicity specify `application/json`. If anything else is provided, an error is returned.
pub fn check_content_type_for_json(req: &Request<Body>) -> Result<(), ApiError> {
match req.headers().get(header::CONTENT_TYPE) {
Some(h) if h == "application/json" => Ok(()),
Some(h) => Err(ApiError::InvalidQueryParams(format!(
"The provided content-type {:?} is not available, it must be JSON.",
h
))),
_ => Ok(()),
}
}
/// Parse a PublicKey from a `0x` prefixed hex string
pub fn parse_pubkey(string: &str) -> Result<PublicKey, ApiError> {
const PREFIX: &str = "0x";
@@ -186,10 +213,11 @@ pub fn state_root_at_slot<T: BeaconChainTypes>(
}
}
pub fn implementation_pending_response(_req: Request<Body>) -> ApiResult {
Err(ApiError::NotImplemented(
pub fn implementation_pending_response(_req: Request<Body>) -> BoxFut {
ApiError::NotImplemented(
"API endpoint has not yet been implemented, but is planned to be soon.".to_owned(),
))
)
.into()
}
pub fn get_beacon_chain_from_request<T: BeaconChainTypes + 'static>(