diff --git a/parity/configuration.rs b/parity/configuration.rs index 856810d3c..08df1d6a6 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -1322,7 +1322,7 @@ mod tests { origins: Some(vec!["chrome-extension://*".into(), "moz-extension://*".into()]), hosts: Some(vec![]), signer_path: expected.into(), - ui_address: Some(("127.0.0.1".to_owned(), 8180)), + ui_address: Some("127.0.0.1:8180".into()), support_token_api: true }, UiConfiguration { enabled: true, diff --git a/parity/dapps.rs b/parity/dapps.rs index b23b759d5..24db4730d 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -57,7 +57,7 @@ impl Default for Configuration { } impl Configuration { - pub fn address(&self, address: Option<(String, u16)>) -> Option<(String, u16)> { + pub fn address(&self, address: Option<::parity_rpc::Host>) -> Option<::parity_rpc::Host> { match self.enabled { true => address, false => None, diff --git a/parity/rpc.rs b/parity/rpc.rs index f11d4c3ae..004e12a28 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -47,11 +47,8 @@ pub struct HttpConfiguration { } impl HttpConfiguration { - pub fn address(&self) -> Option<(String, u16)> { - match self.enabled { - true => Some((self.interface.clone(), self.port)), - false => None, - } + pub fn address(&self) -> Option { + address(self.enabled, &self.interface, self.port, &self.hosts) } } @@ -79,11 +76,18 @@ pub struct UiConfiguration { } impl UiConfiguration { - pub fn address(&self) -> Option<(String, u16)> { - match self.enabled { - true => Some((self.interface.clone(), self.port)), - false => None, - } + pub fn address(&self) -> Option { + address(self.enabled, &self.interface, self.port, &self.hosts) + } + + pub fn redirection_address(&self) -> Option<(String, u16)> { + self.address().map(|host| { + let mut it = host.split(':'); + let hostname: Option = it.next().map(|s| s.to_owned()); + let port: Option = it.next().and_then(|s| s.parse().ok()); + + (hostname.unwrap_or_else(|| "localhost".into()), port.unwrap_or(8180)) + }) } } @@ -145,7 +149,7 @@ pub struct WsConfiguration { pub hosts: Option>, pub signer_path: PathBuf, pub support_token_api: bool, - pub ui_address: Option<(String, u16)>, + pub ui_address: Option, } impl Default for WsConfiguration { @@ -160,17 +164,25 @@ impl Default for WsConfiguration { hosts: Some(Vec::new()), signer_path: replace_home(&data_dir, "$BASE/signer").into(), support_token_api: true, - ui_address: Some(("127.0.0.1".to_owned(), 8180)), + ui_address: Some("127.0.0.1:8180".into()), } } } impl WsConfiguration { - pub fn address(&self) -> Option<(String, u16)> { - match self.enabled { - true => Some((self.interface.clone(), self.port)), - false => None, - } + pub fn address(&self) -> Option { + address(self.enabled, &self.interface, self.port, &self.hosts) + } +} + +fn address(enabled: bool, bind_iface: &str, bind_port: u16, hosts: &Option>) -> Option { + if !enabled { + return None; + } + + match *hosts { + Some(ref hosts) if !hosts.is_empty() => Some(hosts[0].clone().into()), + _ => Some(format!("{}:{}", bind_iface, bind_port).into()), } } @@ -190,17 +202,15 @@ pub fn new_ws( } let domain = DAPPS_DOMAIN; - let ws_address = (conf.interface, conf.port); - let url = format!("{}:{}", ws_address.0, ws_address.1); + let url = format!("{}:{}", conf.interface, conf.port); let addr = url.parse().map_err(|_| format!("Invalid WebSockets listen host/port given: {}", url))?; - let pool = deps.pool.clone(); - let full_handler = setup_apis(rpc_apis::ApiSet::SafeContext, deps, pool.clone()); + let full_handler = setup_apis(rpc_apis::ApiSet::SafeContext, deps); let handler = { let mut handler = MetaIoHandler::with_middleware(( rpc::WsDispatcher::new(full_handler), - Middleware::new(deps.stats.clone(), deps.apis.activity_notifier(), pool) + Middleware::new(deps.stats.clone(), deps.apis.activity_notifier(), deps.pool.clone()) )); let apis = conf.apis.list_apis(); deps.apis.extend_with_set(&mut handler, &apis); @@ -210,8 +220,8 @@ pub fn new_ws( let remote = deps.remote.clone(); let ui_address = conf.ui_address.clone(); - let allowed_origins = into_domains(with_domain(conf.origins, domain, &[ui_address])); - let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &[Some(ws_address)])); + let allowed_origins = into_domains(with_domain(conf.origins, domain, &ui_address)); + let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into()))); let signer_path; let path = match conf.support_token_api && conf.ui_address.is_some() { @@ -253,15 +263,13 @@ pub fn new_http( } let domain = DAPPS_DOMAIN; - let http_address = (conf.interface, conf.port); - let url = format!("{}:{}", http_address.0, http_address.1); + let url = format!("{}:{}", conf.interface, conf.port); let addr = url.parse().map_err(|_| format!("Invalid {} listen host/port given: {}", id, url))?; - let pool = deps.pool.clone(); - let handler = setup_apis(conf.apis, deps, pool); + let handler = setup_apis(conf.apis, deps); let remote = deps.remote.clone(); let cors_domains = into_domains(conf.cors); - let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &[Some(http_address)])); + let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into()))); let start_result = rpc::start_http( &addr, @@ -296,8 +304,7 @@ pub fn new_ipc( return Ok(None); } - let pool = dependencies.pool.clone(); - let handler = setup_apis(conf.apis, dependencies, pool); + let handler = setup_apis(conf.apis, dependencies); let remote = dependencies.remote.clone(); match rpc::start_ipc(&conf.socket_addr, handler, remote, rpc::RpcExtractor) { Ok(server) => Ok(Some(server)), @@ -309,29 +316,46 @@ fn into_domains>(items: Option>) -> DomainsValidatio items.map(|vals| vals.into_iter().map(T::from).collect()).into() } -fn with_domain(items: Option>, domain: &str, addresses: &[Option<(String, u16)>]) -> Option> { +fn with_domain(items: Option>, domain: &str, address: &Option) -> Option> { + fn extract_port(s: &str) -> Option { + s.split(':').nth(1).and_then(|s| s.parse().ok()) + } + items.map(move |items| { let mut items = items.into_iter().collect::>(); - for address in addresses { - if let Some((host, port)) = address.clone() { - items.insert(format!("{}:{}", host, port)); - items.insert(format!("{}:{}", host.replace("127.0.0.1", "localhost"), port)); + if let Some(host) = address.clone() { + items.insert(host.to_string()); + items.insert(host.replace("127.0.0.1", "localhost")); + items.insert(format!("http://*.{}", domain)); //proxypac + if let Some(port) = extract_port(&*host) { items.insert(format!("http://*.{}:{}", domain, port)); - items.insert(format!("http://*.{}", domain)); //proxypac } } items.into_iter().collect() }) } -fn setup_apis(apis: ApiSet, deps: &Dependencies, pool: Option) -> MetaIoHandler> +fn setup_apis(apis: ApiSet, deps: &Dependencies) -> MetaIoHandler> where D: rpc_apis::Dependencies { let mut handler = MetaIoHandler::with_middleware( - Middleware::new(deps.stats.clone(), deps.apis.activity_notifier(), pool) + Middleware::new(deps.stats.clone(), deps.apis.activity_notifier(), deps.pool.clone()) ); let apis = apis.list_apis(); deps.apis.extend_with_set(&mut handler, &apis); handler } + +#[cfg(test)] +mod tests { + use super::address; + + #[test] + fn should_return_proper_address() { + assert_eq!(address(false, "localhost", 8180, &None), None); + assert_eq!(address(true, "localhost", 8180, &None), Some("localhost:8180".into())); + assert_eq!(address(true, "localhost", 8180, &Some(vec!["host:443".into()])), Some("host:443".into())); + assert_eq!(address(true, "localhost", 8180, &Some(vec!["host".into()])), Some("host".into())); + } +} diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 0a2fd87f1..d348202a9 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -37,7 +37,7 @@ use node_health::NodeHealth; use parity_reactor; use parity_rpc::dispatch::{FullDispatcher, LightDispatcher}; use parity_rpc::informant::{ActivityNotifier, ClientNotifier}; -use parity_rpc::{Metadata, NetworkSettings}; +use parity_rpc::{Metadata, NetworkSettings, Host}; use updater::Updater; use parking_lot::{Mutex, RwLock}; @@ -222,8 +222,8 @@ pub struct FullDependencies { pub health: NodeHealth, pub geth_compatibility: bool, pub dapps_service: Option>, - pub dapps_address: Option<(String, u16)>, - pub ws_address: Option<(String, u16)>, + pub dapps_address: Option, + pub ws_address: Option, pub fetch: FetchClient, pub remote: parity_reactor::Remote, pub whisper_rpc: Option<::whisper::RpcFactory>, @@ -412,8 +412,8 @@ pub struct LightDependencies { pub cache: Arc>, pub transaction_queue: Arc>, pub dapps_service: Option>, - pub dapps_address: Option<(String, u16)>, - pub ws_address: Option<(String, u16)>, + pub dapps_address: Option, + pub ws_address: Option, pub fetch: FetchClient, pub geth_compatibility: bool, pub remote: parity_reactor::Remote, diff --git a/parity/run.rs b/parity/run.rs index d0f967410..1ec29e942 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -329,7 +329,7 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc) -> remote: event_loop.raw_remote(), fetch: fetch.clone(), signer: signer_service.clone(), - ui_address: cmd.ui_conf.address(), + ui_address: cmd.ui_conf.redirection_address(), }) }; @@ -723,7 +723,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> R remote: event_loop.raw_remote(), fetch: fetch.clone(), signer: signer_service.clone(), - ui_address: cmd.ui_conf.address(), + ui_address: cmd.ui_conf.redirection_address(), }) }; let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?; diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index fcb452039..f330c75eb 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -51,6 +51,6 @@ pub use self::signer::SignerService; pub use self::subscribers::Subscribers; pub use self::subscription_manager::GenericPollManager; -pub fn to_url(address: &Option<(String, u16)>) -> Option { - address.as_ref().map(|&(ref iface, ref port)| format!("{}:{}", iface, port)) +pub fn to_url(address: &Option<::Host>) -> Option { + address.as_ref().map(|host| (**host).to_owned()) } diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 2f79f66b6..821937edc 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -46,6 +46,7 @@ use v1::types::{ OperationsInfo, DappId, ChainStatus, AccountInfo, HwAccountInfo, Header, RichHeader, }; +use Host; /// Parity implementation for light client. pub struct ParityClient { @@ -55,8 +56,8 @@ pub struct ParityClient { settings: Arc, health: NodeHealth, signer: Option>, - dapps_address: Option<(String, u16)>, - ws_address: Option<(String, u16)>, + dapps_address: Option, + ws_address: Option, eip86_transition: u64, } @@ -70,8 +71,8 @@ impl ParityClient { settings: Arc, health: NodeHealth, signer: Option>, - dapps_address: Option<(String, u16)>, - ws_address: Option<(String, u16)>, + dapps_address: Option, + ws_address: Option, ) -> Self { ParityClient { light_dispatch, diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 434227fcd..b12ed873b 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -51,6 +51,7 @@ use v1::types::{ OperationsInfo, DappId, ChainStatus, AccountInfo, HwAccountInfo, RichHeader }; +use Host; /// Parity implementation. pub struct ParityClient { @@ -64,8 +65,8 @@ pub struct ParityClient { logger: Arc, settings: Arc, signer: Option>, - dapps_address: Option<(String, u16)>, - ws_address: Option<(String, u16)>, + dapps_address: Option, + ws_address: Option, eip86_transition: u64, } @@ -84,8 +85,8 @@ impl ParityClient where logger: Arc, settings: Arc, signer: Option>, - dapps_address: Option<(String, u16)>, - ws_address: Option<(String, u16)>, + dapps_address: Option, + ws_address: Option, ) -> Self { let eip86_transition = client.eip86_transition(); ParityClient { diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 32280804f..ee714c54b 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -31,6 +31,7 @@ use v1::metadata::Metadata; use v1::helpers::{SignerService, NetworkSettings}; use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater}; use super::manage_network::TestManageNetwork; +use Host; pub type TestParityClient = ParityClient; @@ -44,8 +45,8 @@ pub struct Dependencies { pub settings: Arc, pub network: Arc, pub accounts: Arc, - pub dapps_address: Option<(String, u16)>, - pub ws_address: Option<(String, u16)>, + pub dapps_address: Option, + pub ws_address: Option, } impl Dependencies { @@ -74,8 +75,8 @@ impl Dependencies { }), network: Arc::new(TestManageNetwork), accounts: Arc::new(AccountProvider::transient_provider()), - dapps_address: Some(("127.0.0.1".into(), 18080)), - ws_address: Some(("127.0.0.1".into(), 18546)), + dapps_address: Some("127.0.0.1:18080".into()), + ws_address: Some("127.0.0.1:18546".into()), } }