Skip to content

Commit

Permalink
UI server refactoring (openethereum#5580)
Browse files Browse the repository at this point in the history
* Full API in Authenticated WS server.

* Replacing UI server with Hyper.

* Solving CLI, RPCs and tests.

* Porting signer tests.

* Fixing origin recognition for dapps/rpc.

* Fixing tests. Adding parity-rpc-client to test.

* Dapps exposed as RPC method.

* JS code to support new connection scheme.

* Fixing dapps tests.

* Updating allowed origins/hosts to support web3.site.

* Fixing tests, fixing UI.

* Fixing tests.

* Removing invalid tests.

* Fixing merge.

* 404 fallback for UI

* Improve ContentFetcher constructor readability.

* Naming.

* Update .gitlab-ci.yml

fix CI lint error

* Fixing tests and linting issues.

* Fixing new tests.

* UI hosts.

* Submodules fix.
  • Loading branch information
tomusdrw authored and arkpar committed May 24, 2017
1 parent 7499efe commit cbcc369
Show file tree
Hide file tree
Showing 91 changed files with 2,177 additions and 2,597 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ test-windows:
- git submodule update --init --recursive
script:
- set RUST_BACKTRACE=1
- echo cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p parity-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release
- echo cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p parity-dapps -p parity-rpc -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity-rpc-client -p parity %CARGOFLAGS% --verbose --release
tags:
- rust-windows
allow_failure: true
Expand Down
49 changes: 3 additions & 46 deletions Cargo.lock

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

5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ ethcore = { path = "ethcore" }
ethcore-util = { path = "util" }
ethcore-io = { path = "util/io" }
ethcore-devtools = { path = "devtools" }
ethcore-signer = { path = "signer" }
ethcore-ipc = { path = "ipc/rpc" }
ethcore-ipc-nano = { path = "ipc/nano" }
ethcore-ipc-hypervisor = { path = "ipc/hypervisor" }
Expand Down Expand Up @@ -75,17 +74,15 @@ default = ["ui-precompiled"]
ui = [
"dapps",
"parity-dapps/ui",
"ethcore-signer/ui",
]
ui-precompiled = [
"dapps",
"ethcore-signer/ui-precompiled",
"parity-dapps/ui-precompiled",
]
dapps = ["parity-dapps"]
ipc = ["ethcore/ipc", "ethsync/ipc"]
jit = ["ethcore/jit"]
dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "parity-rpc/dev", "parity-dapps/dev", "ethcore-signer/dev"]
dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "parity-rpc/dev", "parity-dapps/dev"]
json-tests = ["ethcore/json-tests"]
test-heavy = ["ethcore/test-heavy"]
ethkey-cli = ["ethcore/ethkey-cli"]
Expand Down
50 changes: 3 additions & 47 deletions dapps/src/api/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,27 @@

use std::sync::Arc;

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

use api::types::{App, ApiError};
use api::types::ApiError;
use api::response;
use apps::fetcher::Fetcher;

use handlers::extract_url;
use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
use jsonrpc_http_server::{self, AccessControlAllowOrigin};
use endpoint::{Endpoint, Handler, EndpointPath};

#[derive(Clone)]
pub struct RestApi {
// TODO [ToDr] cors_domains should be handled by the server to avoid duplicated logic.
// RequestMiddleware should be able to tell that cors headers should be included.
cors_domains: Option<Vec<AccessControlAllowOrigin>>,
apps: Vec<App>,
fetcher: Arc<Fetcher>,
}

impl RestApi {
pub fn new(cors_domains: Vec<AccessControlAllowOrigin>, endpoints: &Endpoints, fetcher: Arc<Fetcher>) -> Box<Endpoint> {
pub fn new(fetcher: Arc<Fetcher>) -> Box<Endpoint> {
Box::new(RestApi {
cors_domains: Some(cors_domains),
apps: Self::list_apps(endpoints),
fetcher: fetcher,
})
}

fn list_apps(endpoints: &Endpoints) -> Vec<App> {
endpoints.iter().filter_map(|(ref k, ref e)| {
e.info().map(|ref info| App::from_info(k, info))
}).collect()
}
}

impl Endpoint for RestApi {
Expand All @@ -62,7 +47,6 @@ impl Endpoint for RestApi {

struct RestApiRouter {
api: RestApi,
cors_header: Option<header::AccessControlAllowOrigin>,
path: Option<EndpointPath>,
control: Option<Control>,
handler: Box<Handler>,
Expand All @@ -72,7 +56,6 @@ impl RestApiRouter {
fn new(api: RestApi, path: EndpointPath, control: Control) -> Self {
RestApiRouter {
path: Some(path),
cors_header: None,
control: Some(control),
api: api,
handler: response::as_json_error(&ApiError {
Expand All @@ -92,35 +75,10 @@ impl RestApiRouter {
_ => None
}
}

/// Returns basic headers for a response (it may be overwritten by the handler)
fn response_headers(cors_header: Option<header::AccessControlAllowOrigin>) -> header::Headers {
let mut headers = header::Headers::new();

if let Some(cors_header) = cors_header {
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()),
]));

headers.set(cors_header);
}

headers
}
}

impl server::Handler<net::HttpStream> for RestApiRouter {
fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next {
self.cors_header = jsonrpc_http_server::cors_header(&request, &self.api.cors_domains).into();

if let Method::Options = *request.method() {
self.handler = response::empty();
return Next::write();
Expand All @@ -144,7 +102,6 @@ impl server::Handler<net::HttpStream> for RestApiRouter {
if let Some(ref hash) = hash { path.app_id = hash.clone().to_owned() }

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

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

Expand Down
1 change: 0 additions & 1 deletion dapps/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ mod response;
mod types;

pub use self::api::RestApi;
pub use self::types::App;
6 changes: 0 additions & 6 deletions dapps/src/api/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ 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");
Box::new(ContentHandler::ok(json, mime!(Application/Json)))
}

pub fn as_json_error<T: Serialize>(val: &T) -> Box<Handler> {
let json = serde_json::to_string(val)
.expect("serialization to string is infallible; qed");
Expand Down
40 changes: 0 additions & 40 deletions dapps/src/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,46 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use endpoint::EndpointInfo;

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct App {
pub id: String,
pub name: String,
pub description: String,
pub version: String,
pub author: String,
#[serde(rename="iconUrl")]
pub icon_url: String,
}

impl App {
/// Creates `App` instance from `EndpointInfo` and `id`.
pub fn from_info(id: &str, info: &EndpointInfo) -> Self {
App {
id: id.to_owned(),
name: info.name.to_owned(),
description: info.description.to_owned(),
version: info.version.to_owned(),
author: info.author.to_owned(),
icon_url: info.icon_url.to_owned(),
}
}
}

impl Into<EndpointInfo> for App {
fn into(self) -> EndpointInfo {
EndpointInfo {
name: self.name,
description: self.description,
version: self.version,
author: self.author,
icon_url: self.icon_url,
}
}
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ApiError {
Expand Down
55 changes: 55 additions & 0 deletions dapps/src/apps/app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

use endpoint::EndpointInfo;

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct App {
pub id: String,
pub name: String,
pub description: String,
pub version: String,
pub author: String,
#[serde(rename="iconUrl")]
pub icon_url: String,
}

impl App {
/// Creates `App` instance from `EndpointInfo` and `id`.
pub fn from_info(id: &str, info: &EndpointInfo) -> Self {
App {
id: id.to_owned(),
name: info.name.to_owned(),
description: info.description.to_owned(),
version: info.version.to_owned(),
author: info.author.to_owned(),
icon_url: info.icon_url.to_owned(),
}
}
}

impl Into<EndpointInfo> for App {
fn into(self) -> EndpointInfo {
EndpointInfo {
name: self.name,
description: self.description,
version: self.version,
author: self.author,
icon_url: self.icon_url,
}
}
}
Loading

0 comments on commit cbcc369

Please sign in to comment.