Supporting topbar injection
This commit is contained in:
parent
0a85df10e8
commit
72b1b41748
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -358,8 +358,9 @@ dependencies = [
|
|||||||
"jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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-idmanager 0.1.1 (git+https://github.com/ethcore/parity-idmanager-rs.git)",
|
||||||
"parity-wallet 0.2.0 (git+https://github.com/ethcore/parity-wallet.git)",
|
"parity-status 0.4.0 (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)",
|
"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)",
|
"url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -820,18 +821,26 @@ name = "odds"
|
|||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parity-idmanager"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "git+https://github.com/ethcore/parity-idmanager-rs.git#5adf8da35e3d3605a6109c53715b867071a0cf57"
|
||||||
|
dependencies = [
|
||||||
|
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-status"
|
name = "parity-status"
|
||||||
version = "0.3.7"
|
version = "0.4.0"
|
||||||
source = "git+https://github.com/ethcore/parity-status.git#b0ae32a7fe2f843e4e22dc38903fd2c3e7fb0763"
|
source = "git+https://github.com/ethcore/parity-status.git#d104bcdbcc84aa8b51e6c194924893e83690b5ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
|
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-wallet"
|
name = "parity-wallet"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/ethcore/parity-wallet.git#18a602fd25f3e9bcdbc5528bf61ba627665d962c"
|
source = "git+https://github.com/ethcore/parity-wallet.git#664fd2b85dd94ca184868bd3965e14a4ba68c03f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
|
"parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)",
|
||||||
]
|
]
|
||||||
|
@ -17,8 +17,9 @@ ethcore-rpc = { path = "../rpc" }
|
|||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
parity-webapp = { git = "https://github.com/ethcore/parity-webapp.git" }
|
parity-webapp = { git = "https://github.com/ethcore/parity-webapp.git" }
|
||||||
# List of apps
|
# List of apps
|
||||||
parity-status = { git = "https://github.com/ethcore/parity-status.git", version = "0.3.7" }
|
parity-status = { git = "https://github.com/ethcore/parity-status.git", version = "0.4.0" }
|
||||||
parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.2.0", optional = true }
|
parity-idmanager = { git = "https://github.com/ethcore/parity-idmanager-rs.git", version = "0.1.1" }
|
||||||
|
parity-wallet = { git = "https://github.com/ethcore/parity-wallet.git", version = "0.3.0", optional = true }
|
||||||
clippy = { version = "0.0.64", optional = true}
|
clippy = { version = "0.0.64", optional = true}
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -14,19 +14,29 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use endpoint::Endpoints;
|
use endpoint::{Endpoints, Endpoint};
|
||||||
use page::PageEndpoint;
|
use page::PageEndpoint;
|
||||||
use proxypac::ProxyPac;
|
use proxypac::ProxyPac;
|
||||||
use parity_webapp::WebApp;
|
use parity_webapp::WebApp;
|
||||||
|
|
||||||
extern crate parity_status;
|
extern crate parity_status;
|
||||||
|
extern crate parity_idmanager;
|
||||||
#[cfg(feature = "parity-wallet")]
|
#[cfg(feature = "parity-wallet")]
|
||||||
extern crate parity_wallet;
|
extern crate parity_wallet;
|
||||||
|
|
||||||
|
pub const DAPPS_DOMAIN : &'static str = ".dapp";
|
||||||
|
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 {
|
pub fn main_page() -> &'static str {
|
||||||
"/status/"
|
"/status/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn utils() -> Box<Endpoint> {
|
||||||
|
Box::new(PageEndpoint::with_prefix(parity_idmanager::App::default(), UTILS_PATH.to_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn all_endpoints() -> Endpoints {
|
pub fn all_endpoints() -> Endpoints {
|
||||||
let mut pages = Endpoints::new();
|
let mut pages = Endpoints::new();
|
||||||
pages.insert("proxy".to_owned(), ProxyPac::boxed());
|
pages.insert("proxy".to_owned(), ProxyPac::boxed());
|
||||||
|
@ -61,11 +61,10 @@ mod proxypac;
|
|||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::collections::HashMap;
|
||||||
use jsonrpc_core::{IoHandler, IoDelegate};
|
use jsonrpc_core::{IoHandler, IoDelegate};
|
||||||
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
|
||||||
|
|
||||||
static DAPPS_DOMAIN : &'static str = ".dapp";
|
|
||||||
|
|
||||||
/// Webapps HTTP+RPC server build.
|
/// Webapps HTTP+RPC server build.
|
||||||
pub struct ServerBuilder {
|
pub struct ServerBuilder {
|
||||||
handler: Arc<IoHandler>,
|
handler: Arc<IoHandler>,
|
||||||
@ -106,17 +105,21 @@ pub struct Server {
|
|||||||
impl Server {
|
impl Server {
|
||||||
fn start_http<A: Authorization + 'static>(addr: &SocketAddr, authorization: A, handler: Arc<IoHandler>) -> Result<Server, ServerError> {
|
fn start_http<A: Authorization + 'static>(addr: &SocketAddr, authorization: A, handler: Arc<IoHandler>) -> Result<Server, ServerError> {
|
||||||
let panic_handler = Arc::new(Mutex::new(None));
|
let panic_handler = Arc::new(Mutex::new(None));
|
||||||
let endpoints = Arc::new(apps::all_endpoints());
|
|
||||||
let authorization = Arc::new(authorization);
|
let authorization = Arc::new(authorization);
|
||||||
let rpc_endpoint = Arc::new(rpc::rpc(handler, panic_handler.clone()));
|
let endpoints = Arc::new(apps::all_endpoints());
|
||||||
let api = Arc::new(api::RestApi::new(endpoints.clone()));
|
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))
|
try!(hyper::Server::http(addr))
|
||||||
.handle(move |_| router::Router::new(
|
.handle(move |_| router::Router::new(
|
||||||
apps::main_page(),
|
apps::main_page(),
|
||||||
endpoints.clone(),
|
endpoints.clone(),
|
||||||
rpc_endpoint.clone(),
|
special.clone(),
|
||||||
api.clone(),
|
|
||||||
authorization.clone(),
|
authorization.clone(),
|
||||||
))
|
))
|
||||||
.map(|l| Server {
|
.map(|l| Server {
|
||||||
|
@ -26,13 +26,23 @@ use endpoint::{Endpoint, EndpointPath};
|
|||||||
use parity_webapp::WebApp;
|
use parity_webapp::WebApp;
|
||||||
|
|
||||||
pub struct PageEndpoint<T : WebApp + 'static> {
|
pub struct PageEndpoint<T : WebApp + 'static> {
|
||||||
|
/// Content of the files
|
||||||
pub app: Arc<T>,
|
pub app: Arc<T>,
|
||||||
|
/// Prefix to strip from the path (when `None` deducted from `app_id`)
|
||||||
|
pub prefix: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: WebApp + 'static> PageEndpoint<T> {
|
impl<T: WebApp + 'static> PageEndpoint<T> {
|
||||||
pub fn new(app: T) -> Self {
|
pub fn new(app: T) -> Self {
|
||||||
PageEndpoint {
|
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<T: WebApp> Endpoint for PageEndpoint<T> {
|
|||||||
fn to_handler(&self, path: EndpointPath) -> Box<server::Handler<HttpStream>> {
|
fn to_handler(&self, path: EndpointPath) -> Box<server::Handler<HttpStream>> {
|
||||||
Box::new(PageHandler {
|
Box::new(PageHandler {
|
||||||
app: self.app.clone(),
|
app: self.app.clone(),
|
||||||
|
prefix: self.prefix.clone(),
|
||||||
path: path,
|
path: path,
|
||||||
file: None,
|
file: None,
|
||||||
write_pos: 0,
|
write_pos: 0,
|
||||||
@ -50,6 +61,7 @@ impl<T: WebApp> Endpoint for PageEndpoint<T> {
|
|||||||
|
|
||||||
struct PageHandler<T: WebApp + 'static> {
|
struct PageHandler<T: WebApp + 'static> {
|
||||||
app: Arc<T>,
|
app: Arc<T>,
|
||||||
|
prefix: Option<String>,
|
||||||
path: EndpointPath,
|
path: EndpointPath,
|
||||||
file: Option<String>,
|
file: Option<String>,
|
||||||
write_pos: usize,
|
write_pos: usize,
|
||||||
@ -57,7 +69,8 @@ struct PageHandler<T: WebApp + 'static> {
|
|||||||
|
|
||||||
impl<T: WebApp + 'static> PageHandler<T> {
|
impl<T: WebApp + 'static> PageHandler<T> {
|
||||||
fn extract_path(&self, path: &str) -> String {
|
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() + "/";
|
let prefix_with_slash = prefix.clone() + "/";
|
||||||
|
|
||||||
// Index file support
|
// Index file support
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
//! Serving ProxyPac file
|
//! Serving ProxyPac file
|
||||||
|
|
||||||
use endpoint::{Endpoint, Handler, ContentHandler, EndpointPath};
|
use endpoint::{Endpoint, Handler, ContentHandler, EndpointPath};
|
||||||
use DAPPS_DOMAIN;
|
use apps::DAPPS_DOMAIN;
|
||||||
|
|
||||||
pub struct ProxyPac;
|
pub struct ProxyPac;
|
||||||
|
|
||||||
|
@ -21,30 +21,32 @@ mod url;
|
|||||||
mod redirect;
|
mod redirect;
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
|
||||||
use DAPPS_DOMAIN;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::collections::HashMap;
|
||||||
use url::Host;
|
use url::Host;
|
||||||
use hyper;
|
use hyper;
|
||||||
use hyper::{server, uri, header};
|
use hyper::{server, uri, header};
|
||||||
use hyper::{Next, Encoder, Decoder};
|
use hyper::{Next, Encoder, Decoder};
|
||||||
use hyper::net::HttpStream;
|
use hyper::net::HttpStream;
|
||||||
|
use apps;
|
||||||
use endpoint::{Endpoint, Endpoints, EndpointPath};
|
use endpoint::{Endpoint, Endpoints, EndpointPath};
|
||||||
use self::url::Url;
|
use self::url::Url;
|
||||||
use self::auth::{Authorization, Authorized};
|
use self::auth::{Authorization, Authorized};
|
||||||
use self::redirect::Redirection;
|
use self::redirect::Redirection;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
/// Special endpoints are accessible on every domain (every dapp)
|
||||||
enum SpecialEndpoint {
|
#[derive(Debug, PartialEq, Hash, Eq)]
|
||||||
|
pub enum SpecialEndpoint {
|
||||||
Rpc,
|
Rpc,
|
||||||
Api,
|
Api,
|
||||||
|
Utils,
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Router<A: Authorization + 'static> {
|
pub struct Router<A: Authorization + 'static> {
|
||||||
main_page: &'static str,
|
main_page: &'static str,
|
||||||
endpoints: Arc<Endpoints>,
|
endpoints: Arc<Endpoints>,
|
||||||
rpc: Arc<Box<Endpoint>>,
|
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
|
||||||
api: Arc<Box<Endpoint>>,
|
|
||||||
authorization: Arc<A>,
|
authorization: Arc<A>,
|
||||||
handler: Box<server::Handler<HttpStream>>,
|
handler: Box<server::Handler<HttpStream>>,
|
||||||
}
|
}
|
||||||
@ -63,13 +65,9 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
|||||||
let endpoint = extract_endpoint(&url);
|
let endpoint = extract_endpoint(&url);
|
||||||
|
|
||||||
match endpoint {
|
match endpoint {
|
||||||
// First check RPC requests
|
// First check special endpoints
|
||||||
(ref path, SpecialEndpoint::Rpc) if *req.method() != hyper::method::Method::Get => {
|
(ref path, ref endpoint) if self.special.contains_key(endpoint) => {
|
||||||
self.rpc.to_handler(path.clone().unwrap_or_default())
|
self.special.get(endpoint).unwrap().to_handler(path.clone().unwrap_or_default())
|
||||||
},
|
|
||||||
// Check API requests
|
|
||||||
(ref path, SpecialEndpoint::Api) => {
|
|
||||||
self.api.to_handler(path.clone().unwrap_or_default())
|
|
||||||
},
|
},
|
||||||
// Then delegate to dapp
|
// Then delegate to dapp
|
||||||
(Some(ref path), _) if self.endpoints.contains_key(&path.app_id) => {
|
(Some(ref path), _) if self.endpoints.contains_key(&path.app_id) => {
|
||||||
@ -81,7 +79,7 @@ impl<A: Authorization + 'static> server::Handler<HttpStream> for Router<A> {
|
|||||||
},
|
},
|
||||||
// RPC by default
|
// RPC by default
|
||||||
_ => {
|
_ => {
|
||||||
self.rpc.to_handler(EndpointPath::default())
|
self.special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,16 +109,14 @@ impl<A: Authorization> Router<A> {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
main_page: &'static str,
|
main_page: &'static str,
|
||||||
endpoints: Arc<Endpoints>,
|
endpoints: Arc<Endpoints>,
|
||||||
rpc: Arc<Box<Endpoint>>,
|
special: Arc<HashMap<SpecialEndpoint, Box<Endpoint>>>,
|
||||||
api: Arc<Box<Endpoint>>,
|
|
||||||
authorization: Arc<A>) -> Self {
|
authorization: Arc<A>) -> Self {
|
||||||
|
|
||||||
let handler = rpc.to_handler(EndpointPath::default());
|
let handler = special.get(&SpecialEndpoint::Rpc).unwrap().to_handler(EndpointPath::default());
|
||||||
Router {
|
Router {
|
||||||
main_page: main_page,
|
main_page: main_page,
|
||||||
endpoints: endpoints,
|
endpoints: endpoints,
|
||||||
rpc: rpc,
|
special: special,
|
||||||
api: api,
|
|
||||||
authorization: authorization,
|
authorization: authorization,
|
||||||
handler: handler,
|
handler: handler,
|
||||||
}
|
}
|
||||||
@ -158,17 +154,19 @@ fn extract_endpoint(url: &Option<Url>) -> (Option<EndpointPath>, SpecialEndpoint
|
|||||||
if url.path.len() <= 1 {
|
if url.path.len() <= 1 {
|
||||||
return SpecialEndpoint::None;
|
return SpecialEndpoint::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match url.path[0].as_ref() {
|
match url.path[0].as_ref() {
|
||||||
"rpc" => SpecialEndpoint::Rpc,
|
apps::RPC_PATH => SpecialEndpoint::Rpc,
|
||||||
"api" => SpecialEndpoint::Api,
|
apps::API_PATH => SpecialEndpoint::Api,
|
||||||
|
apps::UTILS_PATH => SpecialEndpoint::Utils,
|
||||||
_ => SpecialEndpoint::None,
|
_ => SpecialEndpoint::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match *url {
|
match *url {
|
||||||
Some(ref url) => match url.host {
|
Some(ref url) => match url.host {
|
||||||
Host::Domain(ref domain) if domain.ends_with(DAPPS_DOMAIN) => {
|
Host::Domain(ref domain) if domain.ends_with(apps::DAPPS_DOMAIN) => {
|
||||||
let len = domain.len() - DAPPS_DOMAIN.len();
|
let len = domain.len() - apps::DAPPS_DOMAIN.len();
|
||||||
let id = domain[0..len].to_owned();
|
let id = domain[0..len].to_owned();
|
||||||
|
|
||||||
(Some(EndpointPath {
|
(Some(EndpointPath {
|
||||||
@ -215,6 +213,15 @@ fn should_extract_endpoint() {
|
|||||||
}), SpecialEndpoint::Rpc)
|
}), 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
|
// By Subdomain
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_endpoint(&Url::parse("http://my.status.dapp/test.html").ok()),
|
extract_endpoint(&Url::parse("http://my.status.dapp/test.html").ok()),
|
||||||
@ -237,7 +244,7 @@ fn should_extract_endpoint() {
|
|||||||
|
|
||||||
// API by subdomain
|
// API by subdomain
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extract_endpoint(&Url::parse("http://my.status.dapp/rpc/").ok()),
|
extract_endpoint(&Url::parse("http://my.status.dapp/api/").ok()),
|
||||||
(Some(EndpointPath {
|
(Some(EndpointPath {
|
||||||
app_id: "my.status".to_owned(),
|
app_id: "my.status".to_owned(),
|
||||||
host: "my.status.dapp".to_owned(),
|
host: "my.status.dapp".to_owned(),
|
||||||
|
Loading…
Reference in New Issue
Block a user