Skip to content

Commit

Permalink
Add std-http flags
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhauner committed Sep 5, 2020
1 parent de52827 commit 85d4593
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 20 deletions.
41 changes: 33 additions & 8 deletions beacon_node/client/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub struct ClientBuilder<T: BeaconChainTypes> {
network_globals: Option<Arc<NetworkGlobals<T::EthSpec>>>,
network_send: Option<UnboundedSender<NetworkMessage<T::EthSpec>>>,
http_listen_addr: Option<SocketAddr>,
http_api_config: http_api::Config,
websocket_listen_addr: Option<SocketAddr>,
eth_spec_instance: T::EthSpec,
}
Expand Down Expand Up @@ -104,6 +105,7 @@ where
network_globals: None,
network_send: None,
http_listen_addr: None,
http_api_config: <_>::default(),
websocket_listen_addr: None,
eth_spec_instance,
}
Expand Down Expand Up @@ -280,6 +282,12 @@ where
Ok(self)
}

/// Provides configuration for the HTTP API.
pub fn http_api_config(mut self, config: http_api::Config) -> Self {
self.http_api_config = config;
self
}

/// Immediately starts the beacon node REST API http server.
pub fn http_server(
mut self,
Expand Down Expand Up @@ -380,19 +388,36 @@ where
TColdStore,
>,
> {
let http_api_context = Arc::new(http_api::Context {
chain: self.beacon_chain.clone(),
});
let ctx = http_api_context.clone();
self.runtime_context
.unwrap()
.executor
.spawn_without_exit(async move { http_api::serve(ctx).await }, "cats");
let http_api_listen_addr = if self.http_api_config.enabled {
let ctx = Arc::new(http_api::Context {
config: self.http_api_config.clone(),
chain: self.beacon_chain.clone(),
// TODO
log: self.runtime_context.as_ref().unwrap().log().clone(),
});

// TODO
let exit = self.runtime_context.as_ref().unwrap().executor.exit();

let (listen_addr, server) = http_api::serve(ctx, exit)
.map_err(|e| format!("Unable to start HTTP API server: {:?}", e))
.unwrap(); // TODO

self.runtime_context
.unwrap()
.executor
.spawn_without_exit(async move { server.await }, "http-api");

Some(listen_addr)
} else {
None
};

Client {
beacon_chain: self.beacon_chain,
network_globals: self.network_globals,
http_listen_addr: self.http_listen_addr,
http_api_listen_addr,
websocket_listen_addr: self.websocket_listen_addr,
}
}
Expand Down
2 changes: 2 additions & 0 deletions beacon_node/client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub struct Config {
pub chain: beacon_chain::ChainConfig,
pub websocket_server: websocket_server::Config,
pub eth1: eth1::Config,
pub http_api: http_api::Config,
}

impl Default for Config {
Expand All @@ -88,6 +89,7 @@ impl Default for Config {
eth1: <_>::default(),
disabled_forks: Vec::new(),
graffiti: Graffiti::default(),
http_api: <_>::default(),
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions beacon_node/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub struct Client<T: BeaconChainTypes> {
beacon_chain: Option<Arc<BeaconChain<T>>>,
network_globals: Option<Arc<NetworkGlobals<T::EthSpec>>>,
http_listen_addr: Option<SocketAddr>,
/// Listen address for the standard eth2.0 API, if the service was started.
http_api_listen_addr: Option<SocketAddr>,
websocket_listen_addr: Option<SocketAddr>,
}

Expand All @@ -38,6 +40,11 @@ impl<T: BeaconChainTypes> Client<T> {
self.http_listen_addr
}

/// Returns the address of the client's standard eth2.0 API server, if it was started.
pub fn http_api_listen_addr(&self) -> Option<SocketAddr> {
self.http_api_listen_addr
}

/// Returns the address of the client's WebSocket API server, if it was started.
pub fn websocket_listen_addr(&self) -> Option<SocketAddr> {
self.websocket_listen_addr
Expand Down
1 change: 1 addition & 0 deletions beacon_node/http_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ types = { path = "../../consensus/types" }
hex = "0.4.2"
beacon_chain = { path = "../beacon_chain" }
eth2 = { path = "../../common/eth2" }
slog = "2.5.2"


[dev-dependencies]
Expand Down
53 changes: 42 additions & 11 deletions beacon_node/http_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,55 @@ mod state_id;
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
use block_id::BlockId;
use eth2::types::{self as api_types, ValidatorId};
use serde::Serialize;
use serde::{Deserialize, Serialize};
use slog::{crit, info, Logger};
use state_id::StateId;
use std::borrow::Cow;
use std::future::Future;
use std::net::SocketAddr;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::Arc;
use tokio::sync::oneshot;
use types::{CommitteeCache, Epoch, EthSpec, RelativeEpoch};
use warp::Filter;

const API_PREFIX: &str = "eth";
const API_VERSION: &str = "v1";

pub struct Context<T: BeaconChainTypes> {
pub config: Config,
pub chain: Option<Arc<BeaconChain<T>>>,
pub listen_address: [u8; 4],
pub log: Logger,
}

#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub enabled: bool,
pub listen_socket_addr: SocketAddr,
pub listen_addr: Ipv4Addr,
pub listen_port: u16,
}

impl Default for Config {
fn default() -> Self {
Self {
enabled: false,
listen_socket_addr: SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5054).into(),
listen_addr: Ipv4Addr::new(127, 0, 0, 1),
listen_port: 5054,
}
}
}

pub fn serve<T: BeaconChainTypes>(
ctx: Arc<Context<T>>,
) -> Result<(SocketAddr, impl Future<Output = ()>, oneshot::Sender<()>), warp::Error> {
let listen_address = ctx.listen_address;
let listen_port = ctx.listen_port;
shutdown: impl Future<Output = ()> + Send + Sync + 'static,
) -> Result<(SocketAddr, impl Future<Output = ()>), warp::Error> {
let config = ctx.config.clone();
let log = ctx.log.clone();

if config.enabled == false {
crit!(log, "Cannot start disabled HTTP server");
panic!("a disabled server should not be started");
}

let base_path = warp::path(API_PREFIX).and(warp::path(API_VERSION));
let chain_filter = warp::any()
Expand Down Expand Up @@ -423,15 +448,21 @@ pub fn serve<T: BeaconChainTypes>(
.or(beacon_block_root)
.recover(crate::reject::handle_rejection);

let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
// let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown(
(listen_address, listen_port),
SocketAddrV4::new(config.listen_addr, config.listen_port),
async {
shutdown_rx.await.ok();
shutdown.await;
},
)?;

Ok((listening_socket, server, shutdown_tx))
info!(
log,
"HTTP API started";
"listen_address" => listening_socket.to_string(),
);

Ok((listening_socket, server))
}

async fn blocking_task<F, T>(func: F) -> T
Expand Down
23 changes: 23 additions & 0 deletions beacon_node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,29 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.default_value("")
.takes_value(true),
)
/* Standard eth2.0 API related arguments */
.arg(
Arg::with_name("std-http")
.long("std-http")
.help("Enable RESTful HTTP API server. Disabled by default.")
.takes_value(false),
)
.arg(
Arg::with_name("std-http-address")
.long("std-http-address")
.value_name("ADDRESS")
.help("Set the listen address for the RESTful HTTP API server.")
.default_value("127.0.0.1")
.takes_value(true),
)
.arg(
Arg::with_name("std-http-port")
.long("std-http2-port")
.value_name("PORT")
.help("Set the listen TCP port for the RESTful HTTP API server.")
.default_value("5052")
.takes_value(true),
)
/* Websocket related arguments */
.arg(
Arg::with_name("ws")
Expand Down
23 changes: 23 additions & 0 deletions beacon_node/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,29 @@ pub fn get_config<E: EthSpec>(
client_config.rest_api.allow_origin = allow_origin.to_string();
}

/*
* Standard eth2.0 API server
*
* Note: these "std-http" commands are only whilst the API is in beta. Eventually the existing
* HTTP server will be replaced and these flags will disappear.
*/

if cli_args.is_present("std-http") {
client_config.http_api.enabled = true;
}

if let Some(address) = cli_args.value_of("std-http-address") {
client_config.http_api.listen_addr = address
.parse::<Ipv4Addr>()
.map_err(|_| "std-http-address is not a valid IPv4 address.")?;
}

if let Some(port) = cli_args.value_of("std-http-port") {
client_config.http_api.listen_port = port
.parse::<u16>()
.map_err(|_| "std-http-port is not a valid u16.")?;
}

/*
* Websocket server
*/
Expand Down
3 changes: 2 additions & 1 deletion beacon_node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
.build_beacon_chain()?
.network(&client_config.network)
.await?
.notifier()?;
.notifier()?
.http_api_config(client_config.http_api.clone());

let builder = if client_config.rest_api.enabled {
builder.http_server(&client_config, &http_eth2_config, events)?
Expand Down

0 comments on commit 85d4593

Please sign in to comment.