Merge pull request #5399 from paritytech/dapps-content-bug

Fixing disappearing content.
This commit is contained in:
Robert Habermeier 2017-04-07 19:45:48 +02:00 committed by GitHub
commit d0e057cabd
5 changed files with 36 additions and 32 deletions

View File

@ -14,6 +14,8 @@
// 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 std::sync::Arc;
use unicase::UniCase; use unicase::UniCase;
use hyper::{server, net, Decoder, Encoder, Next, Control}; use hyper::{server, net, Decoder, Encoder, Next, Control};
use hyper::header; use hyper::header;
@ -28,16 +30,16 @@ use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
use jsonrpc_http_server::{self, AccessControlAllowOrigin}; use jsonrpc_http_server::{self, AccessControlAllowOrigin};
#[derive(Clone)] #[derive(Clone)]
pub struct RestApi<F> { pub struct RestApi {
// TODO [ToDr] cors_domains should be handled by the server to avoid duplicated logic. // 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. // RequestMiddleware should be able to tell that cors headers should be included.
cors_domains: Option<Vec<AccessControlAllowOrigin>>, cors_domains: Option<Vec<AccessControlAllowOrigin>>,
apps: Vec<App>, apps: Vec<App>,
fetcher: F, fetcher: Arc<Fetcher>,
} }
impl<F: Fetcher + Clone> RestApi<F> { impl RestApi {
pub fn new(cors_domains: Vec<AccessControlAllowOrigin>, endpoints: &Endpoints, fetcher: F) -> Box<Endpoint> { pub fn new(cors_domains: Vec<AccessControlAllowOrigin>, endpoints: &Endpoints, fetcher: Arc<Fetcher>) -> Box<Endpoint> {
Box::new(RestApi { Box::new(RestApi {
cors_domains: Some(cors_domains), cors_domains: Some(cors_domains),
apps: Self::list_apps(endpoints), apps: Self::list_apps(endpoints),
@ -52,22 +54,22 @@ impl<F: Fetcher + Clone> RestApi<F> {
} }
} }
impl<F: Fetcher + Clone> Endpoint for RestApi<F> { impl Endpoint for RestApi {
fn to_async_handler(&self, path: EndpointPath, control: Control) -> Box<Handler> { fn to_async_handler(&self, path: EndpointPath, control: Control) -> Box<Handler> {
Box::new(RestApiRouter::new((*self).clone(), path, control)) Box::new(RestApiRouter::new((*self).clone(), path, control))
} }
} }
struct RestApiRouter<F> { struct RestApiRouter {
api: RestApi<F>, api: RestApi,
cors_header: Option<header::AccessControlAllowOrigin>, cors_header: Option<header::AccessControlAllowOrigin>,
path: Option<EndpointPath>, path: Option<EndpointPath>,
control: Option<Control>, control: Option<Control>,
handler: Box<Handler>, handler: Box<Handler>,
} }
impl<F: Fetcher> RestApiRouter<F> { impl RestApiRouter {
fn new(api: RestApi<F>, path: EndpointPath, control: Control) -> Self { fn new(api: RestApi, path: EndpointPath, control: Control) -> Self {
RestApiRouter { RestApiRouter {
path: Some(path), path: Some(path),
cors_header: None, cors_header: None,
@ -82,6 +84,7 @@ impl<F: Fetcher> RestApiRouter<F> {
} }
fn resolve_content(&self, hash: Option<&str>, path: EndpointPath, control: Control) -> Option<Box<Handler>> { fn resolve_content(&self, hash: Option<&str>, path: EndpointPath, control: Control) -> Option<Box<Handler>> {
trace!(target: "dapps", "Resolving content: {:?} from path: {:?}", hash, path);
match hash { match hash {
Some(hash) if self.api.fetcher.contains(hash) => { Some(hash) if self.api.fetcher.contains(hash) => {
Some(self.api.fetcher.to_async_handler(path, control)) Some(self.api.fetcher.to_async_handler(path, control))
@ -114,8 +117,7 @@ impl<F: Fetcher> RestApiRouter<F> {
} }
} }
impl<F: Fetcher> server::Handler<net::HttpStream> for RestApiRouter<F> { impl server::Handler<net::HttpStream> for RestApiRouter {
fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next { 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(); self.cors_header = jsonrpc_http_server::cors_header(&request, &self.api.cors_domains).into();
@ -168,5 +170,4 @@ impl<F: Fetcher> server::Handler<net::HttpStream> for RestApiRouter<F> {
fn on_response_writable(&mut self, encoder: &mut Encoder<net::HttpStream>) -> Next { fn on_response_writable(&mut self, encoder: &mut Encoder<net::HttpStream>) -> Next {
self.handler.on_response_writable(encoder) self.handler.on_response_writable(encoder)
} }
} }

View File

@ -47,8 +47,7 @@ pub trait Fetcher: Send + Sync + 'static {
fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box<Handler>; fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box<Handler>;
} }
#[derive(Clone)] pub struct ContentFetcher<F: Fetch = FetchClient, R: URLHint + 'static = URLHintContract> {
pub struct ContentFetcher<F: Fetch + Clone = FetchClient, R: URLHint + Clone + 'static = URLHintContract> {
dapps_path: PathBuf, dapps_path: PathBuf,
resolver: R, resolver: R,
cache: Arc<Mutex<ContentCache>>, cache: Arc<Mutex<ContentCache>>,
@ -58,14 +57,14 @@ pub struct ContentFetcher<F: Fetch + Clone = FetchClient, R: URLHint + Clone + '
fetch: F, fetch: F,
} }
impl<R: URLHint + Clone + 'static, F: Fetch + Clone> Drop for ContentFetcher<F, R> { impl<R: URLHint + 'static, F: Fetch> Drop for ContentFetcher<F, R> {
fn drop(&mut self) { fn drop(&mut self) {
// Clear cache path // Clear cache path
let _ = fs::remove_dir_all(&self.dapps_path); let _ = fs::remove_dir_all(&self.dapps_path);
} }
} }
impl<R: URLHint + Clone + 'static, F: Fetch + Clone> ContentFetcher<F, R> { impl<R: URLHint + 'static, F: Fetch> ContentFetcher<F, R> {
pub fn new(resolver: R, sync_status: Arc<SyncStatus>, embeddable_on: Option<(String, u16)>, remote: Remote, fetch: F) -> Self { pub fn new(resolver: R, sync_status: Arc<SyncStatus>, embeddable_on: Option<(String, u16)>, remote: Remote, fetch: F) -> Self {
let mut dapps_path = env::temp_dir(); let mut dapps_path = env::temp_dir();
@ -98,7 +97,7 @@ impl<R: URLHint + Clone + 'static, F: Fetch + Clone> ContentFetcher<F, R> {
} }
} }
impl<R: URLHint + Clone + 'static, F: Fetch + Clone> Fetcher for ContentFetcher<F, R> { impl<R: URLHint + 'static, F: Fetch> Fetcher for ContentFetcher<F, R> {
fn contains(&self, content_id: &str) -> bool { fn contains(&self, content_id: &str) -> bool {
{ {
let mut cache = self.cache.lock(); let mut cache = self.cache.lock();

View File

@ -98,13 +98,13 @@ impl<F> WebProxyTokens for F where F: Fn(String) -> bool + Send + Sync {
} }
/// Dapps server as `jsonrpc-http-server` request middleware. /// Dapps server as `jsonrpc-http-server` request middleware.
pub struct Middleware<F: Fetch + Clone> { pub struct Middleware {
router: router::Router<apps::fetcher::ContentFetcher<F>>, router: router::Router,
} }
impl<F: Fetch + Clone> Middleware<F> { impl Middleware {
/// Creates new Dapps server middleware. /// Creates new Dapps server middleware.
pub fn new( pub fn new<F: Fetch + Clone>(
remote: Remote, remote: Remote,
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
dapps_path: PathBuf, dapps_path: PathBuf,
@ -114,13 +114,13 @@ impl<F: Fetch + Clone> Middleware<F> {
web_proxy_tokens: Arc<WebProxyTokens>, web_proxy_tokens: Arc<WebProxyTokens>,
fetch: F, fetch: F,
) -> Self { ) -> Self {
let content_fetcher = apps::fetcher::ContentFetcher::new( let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new(
hash_fetch::urlhint::URLHintContract::new(registrar), hash_fetch::urlhint::URLHintContract::new(registrar),
sync_status, sync_status,
signer_address.clone(), signer_address.clone(),
remote.clone(), remote.clone(),
fetch.clone(), fetch.clone(),
); ));
let endpoints = apps::all_endpoints( let endpoints = apps::all_endpoints(
dapps_path, dapps_path,
extra_dapps, extra_dapps,
@ -138,7 +138,11 @@ impl<F: Fetch + Clone> Middleware<F> {
special.insert(router::SpecialEndpoint::Utils, Some(apps::utils())); special.insert(router::SpecialEndpoint::Utils, Some(apps::utils()));
special.insert( special.insert(
router::SpecialEndpoint::Api, router::SpecialEndpoint::Api,
Some(api::RestApi::new(cors_domains.clone(), &endpoints, content_fetcher.clone())), Some(api::RestApi::new(
cors_domains.clone(),
&endpoints,
content_fetcher.clone()
)),
); );
special special
}; };
@ -156,7 +160,7 @@ impl<F: Fetch + Clone> Middleware<F> {
} }
} }
impl<F: Fetch + Clone> http::RequestMiddleware for Middleware<F> { impl http::RequestMiddleware for Middleware {
fn on_request(&self, req: &hyper::server::Request<hyper::net::HttpStream>, control: &hyper::Control) -> http::RequestMiddlewareAction { fn on_request(&self, req: &hyper::server::Request<hyper::net::HttpStream>, control: &hyper::Control) -> http::RequestMiddlewareAction {
self.router.on_request(req, control) self.router.on_request(req, control)
} }

View File

@ -19,6 +19,7 @@
use address; use address;
use std::cmp; use std::cmp;
use std::sync::Arc;
use std::collections::HashMap; use std::collections::HashMap;
use url::{Url, Host}; use url::{Url, Host};
@ -40,14 +41,14 @@ pub enum SpecialEndpoint {
None, None,
} }
pub struct Router<F> { pub struct Router {
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
endpoints: Endpoints, endpoints: Endpoints,
fetch: F, fetch: Arc<Fetcher>,
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>, special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
} }
impl<F: Fetcher + 'static> http::RequestMiddleware for Router<F> { impl http::RequestMiddleware for Router {
fn on_request(&self, req: &server::Request<HttpStream>, control: &Control) -> http::RequestMiddlewareAction { fn on_request(&self, req: &server::Request<HttpStream>, control: &Control) -> http::RequestMiddlewareAction {
// Choose proper handler depending on path / domain // Choose proper handler depending on path / domain
let url = handlers::extract_url(req); let url = handlers::extract_url(req);
@ -146,10 +147,10 @@ impl<F: Fetcher + 'static> http::RequestMiddleware for Router<F> {
} }
} }
impl<F> Router<F> { impl Router {
pub fn new( pub fn new(
signer_address: Option<(String, u16)>, signer_address: Option<(String, u16)>,
content_fetcher: F, content_fetcher: Arc<Fetcher>,
endpoints: Endpoints, endpoints: Endpoints,
special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>, special: HashMap<SpecialEndpoint, Option<Box<Endpoint>>>,
) -> Self { ) -> Self {

View File

@ -137,11 +137,10 @@ mod server {
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use hash_fetch::fetch::Client as FetchClient;
use parity_dapps; use parity_dapps;
use parity_reactor; use parity_reactor;
pub type Middleware = parity_dapps::Middleware<FetchClient>; pub use parity_dapps::Middleware;
pub use parity_dapps::SyncStatus; pub use parity_dapps::SyncStatus;
pub fn dapps_middleware( pub fn dapps_middleware(