diff --git a/Cargo.lock b/Cargo.lock
index c6d78d700..2b3d9ccb7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -361,8 +361,9 @@ dependencies = [
"jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "parity-status 0.3.7 (git+https://github.com/ethcore/parity-status.git)",
- "parity-wallet 0.2.0 (git+https://github.com/ethcore/parity-wallet.git)",
+ "parity-idmanager 0.1.3 (git+https://github.com/ethcore/parity-idmanager-rs.git)",
+ "parity-status 0.4.1 (git+https://github.com/ethcore/parity-status.git)",
+ "parity-wallet 0.3.0 (git+https://github.com/ethcore/parity-wallet.git)",
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
"url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -833,18 +834,26 @@ name = "odds"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "parity-idmanager"
+version = "0.1.3"
+source = "git+https://github.com/ethcore/parity-idmanager-rs.git#efb69592b87854f41d8882de75982c8f1e748666"
+dependencies = [
+ "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
+]
+
[[package]]
name = "parity-status"
-version = "0.3.7"
-source = "git+https://github.com/ethcore/parity-status.git#b0ae32a7fe2f843e4e22dc38903fd2c3e7fb0763"
+version = "0.4.1"
+source = "git+https://github.com/ethcore/parity-status.git#f121ebd1f49986545d9fc262ba210cdf07039e6d"
dependencies = [
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
]
[[package]]
name = "parity-wallet"
-version = "0.2.0"
-source = "git+https://github.com/ethcore/parity-wallet.git#18a602fd25f3e9bcdbc5528bf61ba627665d962c"
+version = "0.3.0"
+source = "git+https://github.com/ethcore/parity-wallet.git#664fd2b85dd94ca184868bd3965e14a4ba68c03f"
dependencies = [
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
]
diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml
index 51f54f02d..093136ea4 100644
--- a/webapp/Cargo.toml
+++ b/webapp/Cargo.toml
@@ -17,8 +17,9 @@ ethcore-rpc = { path = "../rpc" }
ethcore-util = { path = "../util" }
parity-webapp = { git = "https://github.com/ethcore/parity-webapp.git" }
# List of apps
-parity-status = { git = "https://github.com/ethcore/parity-status.git", version = "0.3.7" }
-parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.2.0", optional = true }
+parity-status = { git = "https://github.com/ethcore/parity-status.git", version = "0.4.1" }
+parity-idmanager = { git = "https://github.com/ethcore/parity-idmanager-rs.git", version = "0.1.3" }
+parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.3.0", optional = true }
clippy = { version = "0.0.64", optional = true}
[features]
diff --git a/webapp/src/apps.rs b/webapp/src/apps.rs
index c07e9919c..1c9b7e5a8 100644
--- a/webapp/src/apps.rs
+++ b/webapp/src/apps.rs
@@ -14,19 +14,29 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use endpoint::Endpoints;
+use endpoint::{Endpoints, Endpoint};
use page::PageEndpoint;
use proxypac::ProxyPac;
use parity_webapp::WebApp;
extern crate parity_status;
+extern crate parity_idmanager;
#[cfg(feature = "parity-wallet")]
extern crate parity_wallet;
+pub const DAPPS_DOMAIN : &'static str = ".parity";
+pub const RPC_PATH : &'static str = "rpc";
+pub const API_PATH : &'static str = "api";
+pub const UTILS_PATH : &'static str = "parity-utils";
+
pub fn main_page() -> &'static str {
"/status/"
}
+pub fn utils() -> Box {
+ Box::new(PageEndpoint::with_prefix(parity_idmanager::App::default(), UTILS_PATH.to_owned()))
+}
+
pub fn all_endpoints() -> Endpoints {
let mut pages = Endpoints::new();
pages.insert("proxy".to_owned(), ProxyPac::boxed());
diff --git a/webapp/src/lib.rs b/webapp/src/lib.rs
index 2c74dbdc3..819e9d362 100644
--- a/webapp/src/lib.rs
+++ b/webapp/src/lib.rs
@@ -61,6 +61,7 @@ mod proxypac;
use std::sync::{Arc, Mutex};
use std::net::SocketAddr;
+use std::collections::HashMap;
use jsonrpc_core::{IoHandler, IoDelegate};
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
@@ -106,17 +107,21 @@ pub struct Server {
impl Server {
fn start_http(addr: &SocketAddr, authorization: A, handler: Arc) -> Result {
let panic_handler = Arc::new(Mutex::new(None));
- let endpoints = Arc::new(apps::all_endpoints());
let authorization = Arc::new(authorization);
- let rpc_endpoint = Arc::new(rpc::rpc(handler, panic_handler.clone()));
- let api = Arc::new(api::RestApi::new(endpoints.clone()));
+ let endpoints = Arc::new(apps::all_endpoints());
+ let special = Arc::new({
+ let mut special = HashMap::new();
+ special.insert(router::SpecialEndpoint::Rpc, rpc::rpc(handler, panic_handler.clone()));
+ special.insert(router::SpecialEndpoint::Api, api::RestApi::new(endpoints.clone()));
+ special.insert(router::SpecialEndpoint::Utils, apps::utils());
+ special
+ });
try!(hyper::Server::http(addr))
.handle(move |_| router::Router::new(
apps::main_page(),
endpoints.clone(),
- rpc_endpoint.clone(),
- api.clone(),
+ special.clone(),
authorization.clone(),
))
.map(|l| Server {
diff --git a/webapp/src/page/mod.rs b/webapp/src/page/mod.rs
index abcd1930b..1d987c393 100644
--- a/webapp/src/page/mod.rs
+++ b/webapp/src/page/mod.rs
@@ -26,13 +26,23 @@ use endpoint::{Endpoint, EndpointPath};
use parity_webapp::WebApp;
pub struct PageEndpoint {
+ /// Content of the files
pub app: Arc,
+ /// Prefix to strip from the path (when `None` deducted from `app_id`)
+ pub prefix: Option,
}
impl PageEndpoint {
pub fn new(app: T) -> Self {
PageEndpoint {
- app: Arc::new(app)
+ app: Arc::new(app),
+ prefix: None,
+ }
+ }
+ pub fn with_prefix(app: T, prefix: String) -> Self {
+ PageEndpoint {
+ app: Arc::new(app),
+ prefix: Some(prefix),
}
}
}
@@ -41,6 +51,7 @@ impl Endpoint for PageEndpoint {
fn to_handler(&self, path: EndpointPath) -> Box> {
Box::new(PageHandler {
app: self.app.clone(),
+ prefix: self.prefix.clone(),
path: path,
file: None,
write_pos: 0,
@@ -50,6 +61,7 @@ impl Endpoint for PageEndpoint {
struct PageHandler {
app: Arc,
+ prefix: Option,
path: EndpointPath,
file: Option,
write_pos: usize,
@@ -57,7 +69,8 @@ struct PageHandler {
impl PageHandler {
fn extract_path(&self, path: &str) -> String {
- let prefix = "/".to_owned() + &self.path.app_id;
+ let app_id = &self.path.app_id;
+ let prefix = "/".to_owned() + self.prefix.as_ref().unwrap_or(app_id);
let prefix_with_slash = prefix.clone() + "/";
// Index file support
diff --git a/webapp/src/proxypac.rs b/webapp/src/proxypac.rs
index da2cab916..9d91d58f0 100644
--- a/webapp/src/proxypac.rs
+++ b/webapp/src/proxypac.rs
@@ -17,7 +17,7 @@
//! Serving ProxyPac file
use endpoint::{Endpoint, Handler, ContentHandler, EndpointPath};
-use DAPPS_DOMAIN;
+use apps::DAPPS_DOMAIN;
pub struct ProxyPac;
diff --git a/webapp/src/router/mod.rs b/webapp/src/router/mod.rs
index 11205068a..e9d255f95 100644
--- a/webapp/src/router/mod.rs
+++ b/webapp/src/router/mod.rs
@@ -23,28 +23,31 @@ pub mod auth;
use DAPPS_DOMAIN;
use std::sync::Arc;
+use std::collections::HashMap;
use url::Host;
use hyper;
use hyper::{server, uri, header};
use hyper::{Next, Encoder, Decoder};
use hyper::net::HttpStream;
+use apps;
use endpoint::{Endpoint, Endpoints, EndpointPath};
use self::url::Url;
use self::auth::{Authorization, Authorized};
use self::redirect::Redirection;
-#[derive(Debug, PartialEq)]
-enum SpecialEndpoint {
+/// Special endpoints are accessible on every domain (every dapp)
+#[derive(Debug, PartialEq, Hash, Eq)]
+pub enum SpecialEndpoint {
Rpc,
Api,
- None
+ Utils,
+ None,
}
pub struct Router {
main_page: &'static str,
endpoints: Arc,
- rpc: Arc>,
- api: Arc>,
+ special: Arc>>,
authorization: Arc,
handler: Box>,
}
@@ -63,13 +66,9 @@ impl server::Handler for Router {
let endpoint = extract_endpoint(&url);
match endpoint {
- // First check RPC requests
- (ref path, SpecialEndpoint::Rpc) if *req.method() != hyper::method::Method::Get => {
- self.rpc.to_handler(path.clone().unwrap_or_default())
- },
- // Check API requests
- (ref path, SpecialEndpoint::Api) => {
- self.api.to_handler(path.clone().unwrap_or_default())
+ // First check special endpoints
+ (ref path, ref endpoint) if self.special.contains_key(endpoint) => {
+ self.special.get(endpoint).unwrap().to_handler(path.clone().unwrap_or_default())
},
// Then delegate to dapp
(Some(ref path), _) if self.endpoints.contains_key(&path.app_id) => {
@@ -81,7 +80,7 @@ impl server::Handler for Router {
},
// RPC by default
_ => {
- self.rpc.to_handler(EndpointPath::default())
+ self.special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default())
}
}
}
@@ -111,16 +110,14 @@ impl Router {
pub fn new(
main_page: &'static str,
endpoints: Arc,
- rpc: Arc>,
- api: Arc>,
+ special: Arc>>,
authorization: Arc) -> Self {
- let handler = rpc.to_handler(EndpointPath::default());
+ let handler = special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default());
Router {
main_page: main_page,
endpoints: endpoints,
- rpc: rpc,
- api: api,
+ special: special,
authorization: authorization,
handler: handler,
}
@@ -158,9 +155,11 @@ fn extract_endpoint(url: &Option) -> (Option, SpecialEndpoint
if url.path.len() <= 1 {
return SpecialEndpoint::None;
}
+
match url.path[0].as_ref() {
- "rpc" => SpecialEndpoint::Rpc,
- "api" => SpecialEndpoint::Api,
+ apps::RPC_PATH => SpecialEndpoint::Rpc,
+ apps::API_PATH => SpecialEndpoint::Api,
+ apps::UTILS_PATH => SpecialEndpoint::Utils,
_ => SpecialEndpoint::None,
}
}
@@ -215,6 +214,15 @@ fn should_extract_endpoint() {
}), SpecialEndpoint::Rpc)
);
+ assert_eq!(
+ extract_endpoint(&Url::parse("http://my.status.dapp/parity-utils/inject.js").ok()),
+ (Some(EndpointPath {
+ app_id: "my.status".to_owned(),
+ host: "my.status.dapp".to_owned(),
+ port: 80,
+ }), SpecialEndpoint::Utils)
+ );
+
// By Subdomain
assert_eq!(
extract_endpoint(&Url::parse("http://my.status.dapp/test.html").ok()),
@@ -237,7 +245,7 @@ fn should_extract_endpoint() {
// API by subdomain
assert_eq!(
- extract_endpoint(&Url::parse("http://my.status.dapp/rpc/").ok()),
+ extract_endpoint(&Url::parse("http://my.status.dapp/api/").ok()),
(Some(EndpointPath {
app_id: "my.status".to_owned(),
host: "my.status.dapp".to_owned(),