Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Missing changes required to make new UI work #2793

Merged
merged 9 commits into from
Oct 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 3 additions & 28 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 3 additions & 9 deletions dapps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build = "build.rs"
[dependencies]
rand = "0.3.14"
log = "0.3"
env_logger = "0.3"
jsonrpc-core = "3.0"
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc-http-server.git" }
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
Expand All @@ -23,17 +24,13 @@ serde_macros = { version = "0.8", optional = true }
zip = { version = "0.1", default-features = false }
ethabi = "0.2.2"
linked-hash-map = "0.3"
mime = "0.2"
ethcore-devtools = { path = "../devtools" }
ethcore-rpc = { path = "../rpc" }
ethcore-util = { path = "../util" }
fetch = { path = "../util/fetch" }
parity-ui = { path = "./ui" }
parity-dapps-glue = { path = "./js-glue" }
mime = "0.2"
### DEPRECATED
parity-dapps = { git = "https://github.com/ethcore/parity-ui.git", version = "1.4" }
parity-dapps-home = { git = "https://github.com/ethcore/parity-ui.git", version = "1.4" }
### /DEPRECATED

mime_guess = { version = "1.6.1" }
clippy = { version = "0.0.90", optional = true}
Expand All @@ -46,7 +43,4 @@ default = ["serde_codegen"]
nightly = ["serde_macros"]
dev = ["clippy", "ethcore-rpc/dev", "ethcore-util/dev"]

use-precompiled-js = [
"parity-ui/use-precompiled-js",
"parity-dapps-home/use-precompiled-js",
]
use-precompiled-js = ["parity-ui/use-precompiled-js"]
57 changes: 48 additions & 9 deletions dapps/src/api/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,31 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use std::sync::Arc;
use unicase::UniCase;
use hyper::{server, net, Decoder, Encoder, Next, Control};
use hyper::header;
use hyper::method::Method;
use hyper::header::AccessControlAllowOrigin;

use api::types::{App, ApiError};
use api::response::{as_json, as_json_error, ping_response};
use api::response;
use apps::fetcher::ContentFetcher;

use handlers::extract_url;
use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
use apps::fetcher::ContentFetcher;
use jsonrpc_http_server::cors;

#[derive(Clone)]
pub struct RestApi {
local_domain: String,
cors_domains: Option<Vec<AccessControlAllowOrigin>>,
endpoints: Arc<Endpoints>,
fetcher: Arc<ContentFetcher>,
}

impl RestApi {
pub fn new(local_domain: String, endpoints: Arc<Endpoints>, fetcher: Arc<ContentFetcher>) -> Box<Endpoint> {
pub fn new(cors_domains: Vec<String>, endpoints: Arc<Endpoints>, fetcher: Arc<ContentFetcher>) -> Box<Endpoint> {
Box::new(RestApi {
local_domain: local_domain,
cors_domains: Some(cors_domains.into_iter().map(AccessControlAllowOrigin::Value).collect()),
endpoints: endpoints,
fetcher: fetcher,
})
Expand All @@ -53,6 +60,7 @@ impl Endpoint for RestApi {

struct RestApiRouter {
api: RestApi,
origin: Option<String>,
path: Option<EndpointPath>,
control: Option<Control>,
handler: Box<Handler>,
Expand All @@ -62,9 +70,10 @@ impl RestApiRouter {
fn new(api: RestApi, path: EndpointPath, control: Control) -> Self {
RestApiRouter {
path: Some(path),
origin: None,
control: Some(control),
api: api,
handler: as_json_error(&ApiError {
handler: response::as_json_error(&ApiError {
code: "404".into(),
title: "Not Found".into(),
detail: "Resource you requested has not been found.".into(),
Expand All @@ -80,11 +89,40 @@ impl RestApiRouter {
_ => None
}
}

/// Returns basic headers for a response (it may be overwritten by the handler)
fn response_headers(&self) -> header::Headers {
let mut headers = header::Headers::new();
headers.set(header::AccessControlAllowCredentials);
headers.set(header::AccessControlAllowMethods(vec![
Method::Options,
Method::Post,
Method::Get,
]));
headers.set(header::AccessControlAllowHeaders(vec![
UniCase("origin".to_owned()),
UniCase("content-type".to_owned()),
UniCase("accept".to_owned()),
]));

if let Some(cors_header) = cors::get_cors_header(&self.api.cors_domains, &self.origin) {
headers.set(cors_header);
}

headers
}
}

impl server::Handler<net::HttpStream> for RestApiRouter {

fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next {
self.origin = cors::read_origin(&request);

if let Method::Options = *request.method() {
self.handler = response::empty();
return Next::write();
}

let url = extract_url(&request);
if url.is_none() {
// Just return 404 if we can't parse URL
Expand All @@ -99,11 +137,11 @@ impl server::Handler<net::HttpStream> for RestApiRouter {
let hash = url.path.get(2).map(|v| v.as_str());
// at this point path.app_id contains 'api', adjust it to the hash properly, otherwise
// we will try and retrieve 'api' as the hash when doing the /api/content route
if let Some(hash) = hash.clone() { path.app_id = hash.to_owned() }
if let Some(ref hash) = hash { path.app_id = hash.clone().to_owned() }

let handler = endpoint.and_then(|v| match v {
"apps" => Some(as_json(&self.api.list_apps())),
"ping" => Some(ping_response(&self.api.local_domain)),
"apps" => Some(response::as_json(&self.api.list_apps())),
"ping" => Some(response::ping()),
"content" => self.resolve_content(hash, path, control),
_ => None
});
Expand All @@ -121,6 +159,7 @@ impl server::Handler<net::HttpStream> for RestApiRouter {
}

fn on_response(&mut self, res: &mut server::Response) -> Next {
*res.headers_mut() = self.response_headers();
self.handler.on_response(res)
}

Expand Down
Empty file added dapps/src/api/cors.rs
Empty file.
12 changes: 6 additions & 6 deletions dapps/src/api/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ use serde_json;
use endpoint::Handler;
use handlers::{ContentHandler, EchoHandler};

pub fn empty() -> Box<Handler> {
Box::new(ContentHandler::ok("".into(), mime!(Text/Plain)))
}

pub fn as_json<T: Serialize>(val: &T) -> Box<Handler> {
let json = serde_json::to_string(val)
.expect("serialization to string is infallible; qed");
Expand All @@ -31,10 +35,6 @@ pub fn as_json_error<T: Serialize>(val: &T) -> Box<Handler> {
Box::new(ContentHandler::not_found(json, mime!(Application/Json)))
}

pub fn ping_response(local_domain: &str) -> Box<Handler> {
Box::new(EchoHandler::cors(vec![
format!("http://{}", local_domain),
// Allow CORS calls also for localhost
format!("http://{}", local_domain.replace("127.0.0.1", "localhost")),
]))
pub fn ping() -> Box<Handler> {
Box::new(EchoHandler::default())
}
75 changes: 14 additions & 61 deletions dapps/src/apps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,22 @@
use endpoint::{Endpoints, Endpoint};
use page::PageEndpoint;
use proxypac::ProxyPac;
use parity_dapps::{self, WebApp};
use parity_dapps_glue::WebApp as NewWebApp;
use parity_dapps::WebApp;

mod cache;
mod fs;
pub mod urlhint;
pub mod fetcher;
pub mod manifest;

extern crate parity_dapps_home;
extern crate parity_ui;

pub const HOME_PAGE: &'static str = "home";
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 {
"home"
}
pub fn redirection_address(using_dapps_domains: bool, app_id: &str) -> String {
if using_dapps_domains {
format!("http://{}{}/", app_id, DAPPS_DOMAIN)
Expand All @@ -46,72 +42,29 @@ pub fn redirection_address(using_dapps_domains: bool, app_id: &str) -> String {
}

pub fn utils() -> Box<Endpoint> {
Box::new(PageEndpoint::with_prefix(parity_dapps_home::App::default(), UTILS_PATH.to_owned()))
Box::new(PageEndpoint::with_prefix(parity_ui::App::default(), UTILS_PATH.to_owned()))
}

pub fn all_endpoints(dapps_path: String, signer_port: Option<u16>) -> Endpoints {
// fetch fs dapps at first to avoid overwriting builtins
let mut pages = fs::local_endpoints(dapps_path);

// NOTE [ToDr] Dapps will be currently embeded on 8180
pages.insert("ui".into(), Box::new(
PageEndpoint::new_safe_to_embed(NewUi::default(), signer_port)
));

pages.insert("proxy".into(), ProxyPac::boxed());
insert::<parity_dapps_home::App>(&mut pages, "home");

insert::<parity_ui::App>(&mut pages, "ui", Embeddable::Yes(signer_port));
pages.insert("proxy".into(), ProxyPac::boxed(signer_port));

pages
}

fn insert<T : WebApp + Default + 'static>(pages: &mut Endpoints, id: &str) {
pages.insert(id.to_owned(), Box::new(PageEndpoint::new(T::default())));
fn insert<T : WebApp + Default + 'static>(pages: &mut Endpoints, id: &str, embed_at: Embeddable) {
pages.insert(id.to_owned(), Box::new(match embed_at {
Embeddable::Yes(port) => PageEndpoint::new_safe_to_embed(T::default(), port),
Embeddable::No => PageEndpoint::new(T::default()),
}));
}

// TODO [ToDr] Temporary wrapper until we get rid of old built-ins.
use std::collections::HashMap;

struct NewUi {
app: parity_ui::App,
files: HashMap<&'static str, parity_dapps::File>,
}

impl Default for NewUi {
fn default() -> Self {
let app = parity_ui::App::default();
let files = {
let mut files = HashMap::new();
for (k, v) in &app.files {
files.insert(*k, parity_dapps::File {
path: v.path,
content: v.content,
content_type: v.content_type,
});
}
files
};

NewUi {
app: app,
files: files,
}
}
}

impl WebApp for NewUi {
fn file(&self, path: &str) -> Option<&parity_dapps::File> {
self.files.get(path)
}

fn info(&self) -> parity_dapps::Info {
let info = self.app.info();
parity_dapps::Info {
name: info.name,
version: info.version,
author: info.author,
description: info.description,
icon_url: info.icon_url,
}
}
enum Embeddable {
Yes(Option<u16>),
#[allow(dead_code)]
No,
}
Loading