Add ability to configure CORS header (#1345)
## Issue Addressed https://github.com/sigp/lighthouse/issues/1177 ## Proposed Changes Add a command line option (`--http-allow-origin`) and a config item for configuring the `Access-Control-Allow-Origin` response header. This should unblock making XMLHttpRequests.
This commit is contained in:
parent
4a01f44206
commit
fc5e6cbbb0
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -396,6 +396,7 @@ dependencies = [
|
|||||||
"exit-future",
|
"exit-future",
|
||||||
"futures 0.3.5",
|
"futures 0.3.5",
|
||||||
"genesis",
|
"genesis",
|
||||||
|
"hyper 0.13.6",
|
||||||
"logging",
|
"logging",
|
||||||
"node_test_rig",
|
"node_test_rig",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
|
@ -39,3 +39,4 @@ eth2_libp2p = { path = "./eth2_libp2p" }
|
|||||||
eth2_ssz = "0.1.2"
|
eth2_ssz = "0.1.2"
|
||||||
serde = "1.0.110"
|
serde = "1.0.110"
|
||||||
clap_utils = { path = "../common/clap_utils" }
|
clap_utils = { path = "../common/clap_utils" }
|
||||||
|
hyper = "0.13.5"
|
||||||
|
@ -38,6 +38,9 @@ pub struct Config {
|
|||||||
pub listen_address: Ipv4Addr,
|
pub listen_address: Ipv4Addr,
|
||||||
/// The port the REST API HTTP server will listen on.
|
/// The port the REST API HTTP server will listen on.
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
/// If something else than "", a 'Access-Control-Allow-Origin' header will be present in
|
||||||
|
/// responses. Put *, to allow any origin.
|
||||||
|
pub allow_origin: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -46,6 +49,7 @@ impl Default for Config {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
listen_address: Ipv4Addr::new(127, 0, 0, 1),
|
listen_address: Ipv4Addr::new(127, 0, 0, 1),
|
||||||
port: 5052,
|
port: 5052,
|
||||||
|
allow_origin: "".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ pub enum ApiError {
|
|||||||
UnsupportedType(String),
|
UnsupportedType(String),
|
||||||
ImATeapot(String), // Just in case.
|
ImATeapot(String), // Just in case.
|
||||||
ProcessingError(String), // A 202 error, for when a block/attestation cannot be processed, but still transmitted.
|
ProcessingError(String), // A 202 error, for when a block/attestation cannot be processed, but still transmitted.
|
||||||
|
InvalidHeaderValue(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ApiResult = Result<Response<Body>, ApiError>;
|
pub type ApiResult = Result<Response<Body>, ApiError>;
|
||||||
@ -26,6 +27,7 @@ impl ApiError {
|
|||||||
ApiError::UnsupportedType(desc) => (StatusCode::UNSUPPORTED_MEDIA_TYPE, desc),
|
ApiError::UnsupportedType(desc) => (StatusCode::UNSUPPORTED_MEDIA_TYPE, desc),
|
||||||
ApiError::ImATeapot(desc) => (StatusCode::IM_A_TEAPOT, desc),
|
ApiError::ImATeapot(desc) => (StatusCode::IM_A_TEAPOT, desc),
|
||||||
ApiError::ProcessingError(desc) => (StatusCode::ACCEPTED, desc),
|
ApiError::ProcessingError(desc) => (StatusCode::ACCEPTED, desc),
|
||||||
|
ApiError::InvalidHeaderValue(desc) => (StatusCode::INTERNAL_SERVER_ERROR, desc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,6 +79,12 @@ impl From<std::io::Error> for ApiError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<hyper::header::InvalidHeaderValue> for ApiError {
|
||||||
|
fn from(e: hyper::header::InvalidHeaderValue) -> ApiError {
|
||||||
|
ApiError::InvalidHeaderValue(format!("Invalid CORS header value: {:?}", e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl StdError for ApiError {
|
impl StdError for ApiError {
|
||||||
fn cause(&self) -> Option<&dyn StdError> {
|
fn cause(&self) -> Option<&dyn StdError> {
|
||||||
None
|
None
|
||||||
|
@ -64,12 +64,14 @@ pub fn start_server<T: BeaconChainTypes>(
|
|||||||
) -> Result<SocketAddr, hyper::Error> {
|
) -> Result<SocketAddr, hyper::Error> {
|
||||||
let log = executor.log();
|
let log = executor.log();
|
||||||
let inner_log = log.clone();
|
let inner_log = log.clone();
|
||||||
|
let rest_api_config = Arc::new(config.clone());
|
||||||
let eth2_config = Arc::new(eth2_config);
|
let eth2_config = Arc::new(eth2_config);
|
||||||
|
|
||||||
// Define the function that will build the request handler.
|
// Define the function that will build the request handler.
|
||||||
let make_service = make_service_fn(move |_socket: &AddrStream| {
|
let make_service = make_service_fn(move |_socket: &AddrStream| {
|
||||||
let beacon_chain = beacon_chain.clone();
|
let beacon_chain = beacon_chain.clone();
|
||||||
let log = inner_log.clone();
|
let log = inner_log.clone();
|
||||||
|
let rest_api_config = rest_api_config.clone();
|
||||||
let eth2_config = eth2_config.clone();
|
let eth2_config = eth2_config.clone();
|
||||||
let network_globals = network_info.network_globals.clone();
|
let network_globals = network_info.network_globals.clone();
|
||||||
let network_channel = network_info.network_chan.clone();
|
let network_channel = network_info.network_chan.clone();
|
||||||
@ -84,6 +86,7 @@ pub fn start_server<T: BeaconChainTypes>(
|
|||||||
beacon_chain.clone(),
|
beacon_chain.clone(),
|
||||||
network_globals.clone(),
|
network_globals.clone(),
|
||||||
network_channel.clone(),
|
network_channel.clone(),
|
||||||
|
rest_api_config.clone(),
|
||||||
eth2_config.clone(),
|
eth2_config.clone(),
|
||||||
log.clone(),
|
log.clone(),
|
||||||
db_path.clone(),
|
db_path.clone(),
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
advanced, beacon, consensus, error::ApiError, helpers, lighthouse, metrics, network, node,
|
advanced, beacon, config::Config, consensus, error::ApiError, helpers, lighthouse, metrics,
|
||||||
spec, validator, NetworkChannel,
|
network, node, spec, validator, NetworkChannel,
|
||||||
};
|
};
|
||||||
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
use beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use bus::Bus;
|
use bus::Bus;
|
||||||
use eth2_config::Eth2Config;
|
use eth2_config::Eth2Config;
|
||||||
use eth2_libp2p::NetworkGlobals;
|
use eth2_libp2p::NetworkGlobals;
|
||||||
use hyper::{Body, Error, Method, Request, Response};
|
use hyper::header::HeaderValue;
|
||||||
|
use hyper::{Body, Method, Request, Response};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use slog::debug;
|
use slog::debug;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -21,197 +22,220 @@ pub async fn route<T: BeaconChainTypes>(
|
|||||||
beacon_chain: Arc<BeaconChain<T>>,
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
network_globals: Arc<NetworkGlobals<T::EthSpec>>,
|
network_globals: Arc<NetworkGlobals<T::EthSpec>>,
|
||||||
network_channel: NetworkChannel<T::EthSpec>,
|
network_channel: NetworkChannel<T::EthSpec>,
|
||||||
|
rest_api_config: Arc<Config>,
|
||||||
eth2_config: Arc<Eth2Config>,
|
eth2_config: Arc<Eth2Config>,
|
||||||
local_log: slog::Logger,
|
local_log: slog::Logger,
|
||||||
db_path: PathBuf,
|
db_path: PathBuf,
|
||||||
freezer_db_path: PathBuf,
|
freezer_db_path: PathBuf,
|
||||||
events: Arc<Mutex<Bus<SignedBeaconBlockHash>>>,
|
events: Arc<Mutex<Bus<SignedBeaconBlockHash>>>,
|
||||||
) -> Result<Response<Body>, Error> {
|
) -> Result<Response<Body>, ApiError> {
|
||||||
metrics::inc_counter(&metrics::REQUEST_COUNT);
|
metrics::inc_counter(&metrics::REQUEST_COUNT);
|
||||||
let timer = metrics::start_timer(&metrics::REQUEST_RESPONSE_TIME);
|
|
||||||
let received_instant = Instant::now();
|
let received_instant = Instant::now();
|
||||||
|
|
||||||
let path = req.uri().path().to_string();
|
let path = req.uri().path().to_string();
|
||||||
|
|
||||||
let log = local_log.clone();
|
let log = local_log.clone();
|
||||||
let request_result = match (req.method(), path.as_ref()) {
|
let result = {
|
||||||
// Methods for Client
|
let _timer = metrics::start_timer(&metrics::REQUEST_RESPONSE_TIME);
|
||||||
(&Method::GET, "/node/health") => node::get_health(req),
|
|
||||||
(&Method::GET, "/node/version") => node::get_version(req),
|
|
||||||
(&Method::GET, "/node/syncing") => {
|
|
||||||
// inform the current slot, or set to 0
|
|
||||||
let current_slot = beacon_chain
|
|
||||||
.head_info()
|
|
||||||
.map(|info| info.slot)
|
|
||||||
.unwrap_or_else(|_| Slot::from(0u64));
|
|
||||||
|
|
||||||
node::syncing::<T::EthSpec>(req, network_globals, current_slot)
|
match (req.method(), path.as_ref()) {
|
||||||
}
|
// Methods for Client
|
||||||
|
(&Method::GET, "/node/health") => node::get_health(req),
|
||||||
|
(&Method::GET, "/node/version") => node::get_version(req),
|
||||||
|
(&Method::GET, "/node/syncing") => {
|
||||||
|
// inform the current slot, or set to 0
|
||||||
|
let current_slot = beacon_chain
|
||||||
|
.head_info()
|
||||||
|
.map(|info| info.slot)
|
||||||
|
.unwrap_or_else(|_| Slot::from(0u64));
|
||||||
|
|
||||||
// Methods for Network
|
node::syncing::<T::EthSpec>(req, network_globals, current_slot)
|
||||||
(&Method::GET, "/network/enr") => network::get_enr::<T>(req, network_globals),
|
}
|
||||||
(&Method::GET, "/network/peer_count") => network::get_peer_count::<T>(req, network_globals),
|
|
||||||
(&Method::GET, "/network/peer_id") => network::get_peer_id::<T>(req, network_globals),
|
|
||||||
(&Method::GET, "/network/peers") => network::get_peer_list::<T>(req, network_globals),
|
|
||||||
(&Method::GET, "/network/listen_port") => {
|
|
||||||
network::get_listen_port::<T>(req, network_globals)
|
|
||||||
}
|
|
||||||
(&Method::GET, "/network/listen_addresses") => {
|
|
||||||
network::get_listen_addresses::<T>(req, network_globals)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for Beacon Node
|
// Methods for Network
|
||||||
(&Method::GET, "/beacon/head") => beacon::get_head::<T>(req, beacon_chain),
|
(&Method::GET, "/network/enr") => network::get_enr::<T>(req, network_globals),
|
||||||
(&Method::GET, "/beacon/heads") => beacon::get_heads::<T>(req, beacon_chain),
|
(&Method::GET, "/network/peer_count") => {
|
||||||
(&Method::GET, "/beacon/block") => beacon::get_block::<T>(req, beacon_chain),
|
network::get_peer_count::<T>(req, network_globals)
|
||||||
(&Method::GET, "/beacon/block_root") => beacon::get_block_root::<T>(req, beacon_chain),
|
}
|
||||||
(&Method::GET, "/beacon/fork") => beacon::get_fork::<T>(req, beacon_chain),
|
(&Method::GET, "/network/peer_id") => network::get_peer_id::<T>(req, network_globals),
|
||||||
(&Method::GET, "/beacon/fork/stream") => {
|
(&Method::GET, "/network/peers") => network::get_peer_list::<T>(req, network_globals),
|
||||||
let reader = events.lock().add_rx();
|
(&Method::GET, "/network/listen_port") => {
|
||||||
beacon::stream_forks::<T>(log, reader)
|
network::get_listen_port::<T>(req, network_globals)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/beacon/genesis_time") => beacon::get_genesis_time::<T>(req, beacon_chain),
|
(&Method::GET, "/network/listen_addresses") => {
|
||||||
(&Method::GET, "/beacon/genesis_validators_root") => {
|
network::get_listen_addresses::<T>(req, network_globals)
|
||||||
beacon::get_genesis_validators_root::<T>(req, beacon_chain)
|
}
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/validators") => beacon::get_validators::<T>(req, beacon_chain),
|
|
||||||
(&Method::POST, "/beacon/validators") => {
|
|
||||||
beacon::post_validators::<T>(req, beacon_chain).await
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/validators/all") => {
|
|
||||||
beacon::get_all_validators::<T>(req, beacon_chain)
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/validators/active") => {
|
|
||||||
beacon::get_active_validators::<T>(req, beacon_chain)
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/state") => beacon::get_state::<T>(req, beacon_chain),
|
|
||||||
(&Method::GET, "/beacon/state_root") => beacon::get_state_root::<T>(req, beacon_chain),
|
|
||||||
(&Method::GET, "/beacon/state/genesis") => {
|
|
||||||
beacon::get_genesis_state::<T>(req, beacon_chain)
|
|
||||||
}
|
|
||||||
(&Method::GET, "/beacon/committees") => beacon::get_committees::<T>(req, beacon_chain),
|
|
||||||
(&Method::POST, "/beacon/proposer_slashing") => {
|
|
||||||
beacon::proposer_slashing::<T>(req, beacon_chain).await
|
|
||||||
}
|
|
||||||
(&Method::POST, "/beacon/attester_slashing") => {
|
|
||||||
beacon::attester_slashing::<T>(req, beacon_chain).await
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for Validator
|
// Methods for Beacon Node
|
||||||
(&Method::POST, "/validator/duties") => {
|
(&Method::GET, "/beacon/head") => beacon::get_head::<T>(req, beacon_chain),
|
||||||
let timer = metrics::start_timer(&metrics::VALIDATOR_GET_DUTIES_REQUEST_RESPONSE_TIME);
|
(&Method::GET, "/beacon/heads") => beacon::get_heads::<T>(req, beacon_chain),
|
||||||
let response = validator::post_validator_duties::<T>(req, beacon_chain);
|
(&Method::GET, "/beacon/block") => beacon::get_block::<T>(req, beacon_chain),
|
||||||
drop(timer);
|
(&Method::GET, "/beacon/block_root") => beacon::get_block_root::<T>(req, beacon_chain),
|
||||||
response.await
|
(&Method::GET, "/beacon/fork") => beacon::get_fork::<T>(req, beacon_chain),
|
||||||
}
|
(&Method::GET, "/beacon/fork/stream") => {
|
||||||
(&Method::POST, "/validator/subscribe") => {
|
let reader = events.lock().add_rx();
|
||||||
validator::post_validator_subscriptions::<T>(req, network_channel).await
|
beacon::stream_forks::<T>(log, reader)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/validator/duties/all") => {
|
(&Method::GET, "/beacon/genesis_time") => {
|
||||||
validator::get_all_validator_duties::<T>(req, beacon_chain)
|
beacon::get_genesis_time::<T>(req, beacon_chain)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/validator/duties/active") => {
|
(&Method::GET, "/beacon/genesis_validators_root") => {
|
||||||
validator::get_active_validator_duties::<T>(req, beacon_chain)
|
beacon::get_genesis_validators_root::<T>(req, beacon_chain)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/validator/block") => {
|
(&Method::GET, "/beacon/validators") => beacon::get_validators::<T>(req, beacon_chain),
|
||||||
let timer = metrics::start_timer(&metrics::VALIDATOR_GET_BLOCK_REQUEST_RESPONSE_TIME);
|
(&Method::POST, "/beacon/validators") => {
|
||||||
let response = validator::get_new_beacon_block::<T>(req, beacon_chain, log);
|
beacon::post_validators::<T>(req, beacon_chain).await
|
||||||
drop(timer);
|
}
|
||||||
response
|
(&Method::GET, "/beacon/validators/all") => {
|
||||||
}
|
beacon::get_all_validators::<T>(req, beacon_chain)
|
||||||
(&Method::POST, "/validator/block") => {
|
}
|
||||||
validator::publish_beacon_block::<T>(req, beacon_chain, network_channel, log).await
|
(&Method::GET, "/beacon/validators/active") => {
|
||||||
}
|
beacon::get_active_validators::<T>(req, beacon_chain)
|
||||||
(&Method::GET, "/validator/attestation") => {
|
}
|
||||||
let timer =
|
(&Method::GET, "/beacon/state") => beacon::get_state::<T>(req, beacon_chain),
|
||||||
metrics::start_timer(&metrics::VALIDATOR_GET_ATTESTATION_REQUEST_RESPONSE_TIME);
|
(&Method::GET, "/beacon/state_root") => beacon::get_state_root::<T>(req, beacon_chain),
|
||||||
let response = validator::get_new_attestation::<T>(req, beacon_chain);
|
(&Method::GET, "/beacon/state/genesis") => {
|
||||||
drop(timer);
|
beacon::get_genesis_state::<T>(req, beacon_chain)
|
||||||
response
|
}
|
||||||
}
|
(&Method::GET, "/beacon/committees") => beacon::get_committees::<T>(req, beacon_chain),
|
||||||
(&Method::GET, "/validator/aggregate_attestation") => {
|
(&Method::POST, "/beacon/proposer_slashing") => {
|
||||||
validator::get_aggregate_attestation::<T>(req, beacon_chain)
|
beacon::proposer_slashing::<T>(req, beacon_chain).await
|
||||||
}
|
}
|
||||||
(&Method::POST, "/validator/attestations") => {
|
(&Method::POST, "/beacon/attester_slashing") => {
|
||||||
validator::publish_attestations::<T>(req, beacon_chain, network_channel, log).await
|
beacon::attester_slashing::<T>(req, beacon_chain).await
|
||||||
}
|
}
|
||||||
(&Method::POST, "/validator/aggregate_and_proofs") => {
|
|
||||||
validator::publish_aggregate_and_proofs::<T>(req, beacon_chain, network_channel, log)
|
// Methods for Validator
|
||||||
|
(&Method::POST, "/validator/duties") => {
|
||||||
|
let timer =
|
||||||
|
metrics::start_timer(&metrics::VALIDATOR_GET_DUTIES_REQUEST_RESPONSE_TIME);
|
||||||
|
let response = validator::post_validator_duties::<T>(req, beacon_chain);
|
||||||
|
drop(timer);
|
||||||
|
response.await
|
||||||
|
}
|
||||||
|
(&Method::POST, "/validator/subscribe") => {
|
||||||
|
validator::post_validator_subscriptions::<T>(req, network_channel).await
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/duties/all") => {
|
||||||
|
validator::get_all_validator_duties::<T>(req, beacon_chain)
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/duties/active") => {
|
||||||
|
validator::get_active_validator_duties::<T>(req, beacon_chain)
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/block") => {
|
||||||
|
let timer =
|
||||||
|
metrics::start_timer(&metrics::VALIDATOR_GET_BLOCK_REQUEST_RESPONSE_TIME);
|
||||||
|
let response = validator::get_new_beacon_block::<T>(req, beacon_chain, log);
|
||||||
|
drop(timer);
|
||||||
|
response
|
||||||
|
}
|
||||||
|
(&Method::POST, "/validator/block") => {
|
||||||
|
validator::publish_beacon_block::<T>(req, beacon_chain, network_channel, log).await
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/attestation") => {
|
||||||
|
let timer =
|
||||||
|
metrics::start_timer(&metrics::VALIDATOR_GET_ATTESTATION_REQUEST_RESPONSE_TIME);
|
||||||
|
let response = validator::get_new_attestation::<T>(req, beacon_chain);
|
||||||
|
drop(timer);
|
||||||
|
response
|
||||||
|
}
|
||||||
|
(&Method::GET, "/validator/aggregate_attestation") => {
|
||||||
|
validator::get_aggregate_attestation::<T>(req, beacon_chain)
|
||||||
|
}
|
||||||
|
(&Method::POST, "/validator/attestations") => {
|
||||||
|
validator::publish_attestations::<T>(req, beacon_chain, network_channel, log).await
|
||||||
|
}
|
||||||
|
(&Method::POST, "/validator/aggregate_and_proofs") => {
|
||||||
|
validator::publish_aggregate_and_proofs::<T>(
|
||||||
|
req,
|
||||||
|
beacon_chain,
|
||||||
|
network_channel,
|
||||||
|
log,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods for consensus
|
// Methods for consensus
|
||||||
(&Method::GET, "/consensus/global_votes") => {
|
(&Method::GET, "/consensus/global_votes") => {
|
||||||
consensus::get_vote_count::<T>(req, beacon_chain)
|
consensus::get_vote_count::<T>(req, beacon_chain)
|
||||||
}
|
}
|
||||||
(&Method::POST, "/consensus/individual_votes") => {
|
(&Method::POST, "/consensus/individual_votes") => {
|
||||||
consensus::post_individual_votes::<T>(req, beacon_chain).await
|
consensus::post_individual_votes::<T>(req, beacon_chain).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods for bootstrap and checking configuration
|
// Methods for bootstrap and checking configuration
|
||||||
(&Method::GET, "/spec") => spec::get_spec::<T>(req, beacon_chain),
|
(&Method::GET, "/spec") => spec::get_spec::<T>(req, beacon_chain),
|
||||||
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
(&Method::GET, "/spec/slots_per_epoch") => spec::get_slots_per_epoch::<T>(req),
|
||||||
(&Method::GET, "/spec/deposit_contract") => helpers::implementation_pending_response(req),
|
(&Method::GET, "/spec/deposit_contract") => {
|
||||||
(&Method::GET, "/spec/eth2_config") => spec::get_eth2_config::<T>(req, eth2_config),
|
helpers::implementation_pending_response(req)
|
||||||
|
}
|
||||||
|
(&Method::GET, "/spec/eth2_config") => spec::get_eth2_config::<T>(req, eth2_config),
|
||||||
|
|
||||||
// Methods for advanced parameters
|
// Methods for advanced parameters
|
||||||
(&Method::GET, "/advanced/fork_choice") => {
|
(&Method::GET, "/advanced/fork_choice") => {
|
||||||
advanced::get_fork_choice::<T>(req, beacon_chain)
|
advanced::get_fork_choice::<T>(req, beacon_chain)
|
||||||
}
|
}
|
||||||
(&Method::GET, "/advanced/operation_pool") => {
|
(&Method::GET, "/advanced/operation_pool") => {
|
||||||
advanced::get_operation_pool::<T>(req, beacon_chain)
|
advanced::get_operation_pool::<T>(req, beacon_chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
(&Method::GET, "/metrics") => {
|
(&Method::GET, "/metrics") => {
|
||||||
metrics::get_prometheus::<T>(req, beacon_chain, db_path, freezer_db_path)
|
metrics::get_prometheus::<T>(req, beacon_chain, db_path, freezer_db_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lighthouse specific
|
// Lighthouse specific
|
||||||
(&Method::GET, "/lighthouse/syncing") => {
|
(&Method::GET, "/lighthouse/syncing") => {
|
||||||
lighthouse::syncing::<T::EthSpec>(req, network_globals)
|
lighthouse::syncing::<T::EthSpec>(req, network_globals)
|
||||||
}
|
}
|
||||||
|
|
||||||
(&Method::GET, "/lighthouse/peers") => {
|
(&Method::GET, "/lighthouse/peers") => {
|
||||||
lighthouse::peers::<T::EthSpec>(req, network_globals)
|
lighthouse::peers::<T::EthSpec>(req, network_globals)
|
||||||
}
|
}
|
||||||
|
|
||||||
(&Method::GET, "/lighthouse/connected_peers") => {
|
(&Method::GET, "/lighthouse/connected_peers") => {
|
||||||
lighthouse::connected_peers::<T::EthSpec>(req, network_globals)
|
lighthouse::connected_peers::<T::EthSpec>(req, network_globals)
|
||||||
|
}
|
||||||
|
_ => Err(ApiError::NotFound(
|
||||||
|
"Request path and/or method not found.".to_owned(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
_ => Err(ApiError::NotFound(
|
|
||||||
"Request path and/or method not found.".to_owned(),
|
|
||||||
)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let request_processing_duration = Instant::now().duration_since(received_instant);
|
||||||
|
|
||||||
// Map the Rust-friendly `Result` in to a http-friendly response. In effect, this ensures that
|
// Map the Rust-friendly `Result` in to a http-friendly response. In effect, this ensures that
|
||||||
// any `Err` returned from our response handlers becomes a valid http response to the client
|
// any `Err` returned from our response handlers becomes a valid http response to the client
|
||||||
// (e.g., a response with a 404 or 500 status).
|
// (e.g., a response with a 404 or 500 status).
|
||||||
let duration = Instant::now().duration_since(received_instant);
|
|
||||||
match request_result {
|
match result {
|
||||||
Ok(response) => {
|
Ok(mut response) => {
|
||||||
|
if rest_api_config.allow_origin != "" {
|
||||||
|
let headers = response.headers_mut();
|
||||||
|
headers.insert(
|
||||||
|
hyper::header::ACCESS_CONTROL_ALLOW_ORIGIN,
|
||||||
|
HeaderValue::from_str(&rest_api_config.allow_origin)?,
|
||||||
|
);
|
||||||
|
headers.insert(hyper::header::VARY, HeaderValue::from_static("Origin"));
|
||||||
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
local_log,
|
local_log,
|
||||||
"HTTP API request successful";
|
"HTTP API request successful";
|
||||||
"path" => path,
|
"path" => path,
|
||||||
"duration_ms" => duration.as_millis()
|
"duration_ms" => request_processing_duration.as_millis()
|
||||||
);
|
);
|
||||||
metrics::inc_counter(&metrics::SUCCESS_COUNT);
|
metrics::inc_counter(&metrics::SUCCESS_COUNT);
|
||||||
metrics::stop_timer(timer);
|
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
|
||||||
let error_response = e.into();
|
|
||||||
|
|
||||||
|
Err(error) => {
|
||||||
debug!(
|
debug!(
|
||||||
local_log,
|
local_log,
|
||||||
"HTTP API request failure";
|
"HTTP API request failure";
|
||||||
"path" => path,
|
"path" => path,
|
||||||
"duration_ms" => duration.as_millis()
|
"duration_ms" => request_processing_duration.as_millis()
|
||||||
);
|
);
|
||||||
metrics::stop_timer(timer);
|
Ok(error.into())
|
||||||
|
|
||||||
Ok(error_response)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,6 +161,14 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
|||||||
.default_value("5052")
|
.default_value("5052")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("http-allow-origin")
|
||||||
|
.long("http-allow-origin")
|
||||||
|
.value_name("ORIGIN")
|
||||||
|
.help("Set the value of the Access-Control-Allow-Origin response HTTP header. Use * to allow any origin (not recommended in production)")
|
||||||
|
.default_value("")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
/* Websocket related arguments */
|
/* Websocket related arguments */
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("ws")
|
Arg::with_name("ws")
|
||||||
|
@ -4,6 +4,7 @@ use clap_utils::BAD_TESTNET_DIR_MESSAGE;
|
|||||||
use client::{config::DEFAULT_DATADIR, ClientConfig, ClientGenesis};
|
use client::{config::DEFAULT_DATADIR, ClientConfig, ClientGenesis};
|
||||||
use eth2_libp2p::{Enr, Multiaddr};
|
use eth2_libp2p::{Enr, Multiaddr};
|
||||||
use eth2_testnet_config::Eth2TestnetConfig;
|
use eth2_testnet_config::Eth2TestnetConfig;
|
||||||
|
use hyper;
|
||||||
use slog::{crit, info, Logger};
|
use slog::{crit, info, Logger};
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -220,6 +221,15 @@ pub fn get_config<E: EthSpec>(
|
|||||||
.map_err(|_| "http-port is not a valid u16.")?;
|
.map_err(|_| "http-port is not a valid u16.")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(allow_origin) = cli_args.value_of("http-allow-origin") {
|
||||||
|
// Pre-validate the config value to give feedback to the user on node startup, instead of
|
||||||
|
// as late as when the first API response is produced.
|
||||||
|
hyper::header::HeaderValue::from_str(allow_origin)
|
||||||
|
.map_err(|_| "Invalid allow-origin value")?;
|
||||||
|
|
||||||
|
client_config.rest_api.allow_origin = allow_origin.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Websocket server
|
* Websocket server
|
||||||
*/
|
*/
|
||||||
|
@ -20,7 +20,6 @@ pub const VERSION: &str = git_version!(
|
|||||||
fallback = crate_version!()
|
fallback = crate_version!()
|
||||||
);
|
);
|
||||||
pub const DEFAULT_DATA_DIR: &str = ".lighthouse";
|
pub const DEFAULT_DATA_DIR: &str = ".lighthouse";
|
||||||
pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
|
|
||||||
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
|
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user