Fixing deprecated methods of tokio_core

This commit is contained in:
Tomasz Drwięga 2017-03-16 15:43:31 +01:00
parent 491eeb9878
commit 579cff478d
No known key found for this signature in database
GPG Key ID: D066F497E62CAF66
12 changed files with 158 additions and 67 deletions

57
Cargo.lock generated
View File

@ -409,7 +409,7 @@ dependencies = [
"ethstore 0.1.0",
"evmjit 1.7.0",
"hardware-wallet 1.7.0",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -455,7 +455,6 @@ dependencies = [
"ethcore-util 1.7.0",
"fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
@ -661,7 +660,7 @@ dependencies = [
"ethcore-util 1.7.0",
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1001,7 +1000,26 @@ dependencies = [
[[package]]
name = "hyper"
version = "0.10.4"
version = "0.10.0-a.0"
source = "git+https://github.com/paritytech/hyper#453c683b52208fefc32d29e4ac7c863439b2321f"
dependencies = [
"cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rotor 0.6.3 (git+https://github.com/ethcore/rotor)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hyper"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1012,7 +1030,7 @@ dependencies = [
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1024,7 +1042,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1100,7 +1118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonrpc-core"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1112,9 +1130,9 @@ dependencies = [
[[package]]
name = "jsonrpc-http-server"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1125,7 +1143,7 @@ dependencies = [
[[package]]
name = "jsonrpc-ipc-server"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
@ -1137,7 +1155,7 @@ dependencies = [
[[package]]
name = "jsonrpc-macros"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-pubsub 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
@ -1147,7 +1165,7 @@ dependencies = [
[[package]]
name = "jsonrpc-pubsub"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1157,7 +1175,7 @@ dependencies = [
[[package]]
name = "jsonrpc-server-utils"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1168,7 +1186,7 @@ dependencies = [
[[package]]
name = "jsonrpc-tcp-server"
version = "7.0.0"
source = "git+https://github.com/ethcore/jsonrpc.git#4706ebc240f15eed85a2670660576541fdda7bbb"
source = "git+https://github.com/ethcore/jsonrpc.git#50f69e145f59305df6c22917e8dbb9b27a73a285"
dependencies = [
"jsonrpc-core 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
"jsonrpc-server-utils 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
@ -1951,7 +1969,7 @@ name = "reqwest"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2479,6 +2497,11 @@ name = "traitobject"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "transient-hashmap"
version = "0.1.0"
@ -2700,7 +2723,8 @@ dependencies = [
"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
"checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae"
"checksum hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)" = "<none>"
"checksum hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "220407e5a263f110ec30a071787c9535918fdfc97def5680c90013c3f30c38c1"
"checksum hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)" = "<none>"
"checksum hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "43a15e3273b2133aaac0150478ab443fb89f15c3de41d8d93d8f3bb14bf560f6"
"checksum hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9bf64f730d6ee4b0528a5f0a316363da9d8104318731509d4ccc86248f82b3"
"checksum hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "afe68f772f0497a7205e751626bb8e1718568b58534b6108c73a74ef80483409"
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
@ -2852,6 +2876,7 @@ dependencies = [
"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6"
"checksum toml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442dfc13508e603c3f763274361db7f79d7469a0e95c411cde53662ab30fc72"
"checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15f7cc7116182edca1ed08f6f8c4da92104555ca77addbabea4eaa59b20373d0"
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"

View File

@ -25,7 +25,6 @@ unicase = "1.3"
url = "1.0"
zip = { version = "0.1", default-features = false }
hyper = { default-features = false, git = "https://github.com/ethcore/hyper" }
jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git", branch = "master" }
jsonrpc-http-server = { git = "https://github.com/ethcore/jsonrpc.git", branch = "master" }
# TODO [ToDr] Temporary solution, server should be merged with RPC.

View File

@ -21,7 +21,6 @@
extern crate base32;
extern crate futures;
extern crate hyper;
extern crate linked_hash_map;
extern crate mime_guess;
extern crate rand;
@ -78,6 +77,7 @@ use std::collections::HashMap;
use jsonrpc_core::{Middleware, MetaIoHandler};
use jsonrpc_http_server::tokio_core::reactor::Remote as TokioRemote;
pub use jsonrpc_http_server::{DomainsValidation, Host, AccessControlAllowOrigin};
pub use jsonrpc_http_server::hyper;
use ethcore_rpc::Metadata;
use fetch::{Fetch, Client as FetchClient};

View File

@ -46,15 +46,6 @@ struct RpcEndpoint<T: Middleware<Metadata>> {
allowed_hosts: Option<Vec<http::Host>>,
}
#[derive(Default)]
struct NoopMiddleware;
impl http::RequestMiddleware for NoopMiddleware {
fn on_request(&self, request: &hyper::server::Request<hyper::net::HttpStream>) -> http::RequestMiddlewareAction {
http::RequestMiddlewareAction::Proceed {
should_continue_on_invalid_cors: request.headers().get::<hyper::header::Origin>().is_none(),
}
}
}
impl<T: Middleware<Metadata>> Endpoint for RpcEndpoint<T> {
fn to_async_handler(&self, _path: EndpointPath, control: hyper::Control) -> Box<Handler> {
@ -72,10 +63,20 @@ impl<T: Middleware<Metadata>> Endpoint for RpcEndpoint<T> {
}
}
#[derive(Default)]
struct NoopMiddleware;
impl http::RequestMiddleware for NoopMiddleware {
fn on_request(&self, request: &http::hyper::server::Request<http::hyper::net::HttpStream>) -> http::RequestMiddlewareAction {
http::RequestMiddlewareAction::Proceed {
should_continue_on_invalid_cors: request.headers().get::<http::hyper::header::Origin>().is_none(),
}
}
}
struct MetadataExtractor;
impl HttpMetaExtractor<Metadata> for MetadataExtractor {
fn read_metadata(&self, request: &hyper::server::Request<hyper::net::HttpStream>) -> Metadata {
let dapp_id = request.headers().get::<hyper::header::Origin>()
fn read_metadata(&self, request: &http::hyper::server::Request<http::hyper::net::HttpStream>) -> Metadata {
let dapp_id = request.headers().get::<http::hyper::header::Origin>()
.map(|origin| format!("{}://{}", origin.scheme, origin.host))
.or_else(|| {
// fallback to custom header, but only if origin is null

View File

@ -114,7 +114,7 @@ impl Fetch for FakeFetch {
let data = response.lock().take().unwrap_or(b"Some content");
let cursor = io::Cursor::new(data);
tx.complete(fetch::Response::from_reader(cursor));
tx.send(fetch::Response::from_reader(cursor)).unwrap();
});
rx.map_err(|_| fetch::Error::Aborted).boxed()

View File

@ -55,8 +55,8 @@ fn should_extract_metadata() {
// given
let mut io = MetaIoHandler::default();
io.add_method_with_meta("rpc_test", |_params, meta: Metadata| {
assert_eq!(meta.origin, Origin::Dapps("https://parity.io/".into()));
assert_eq!(meta.dapp_id(), "https://parity.io/".into());
assert_eq!(meta.origin, Origin::Dapps("".into()));
assert_eq!(meta.dapp_id(), "".into());
future::ok(Value::String("Hello World!".into())).boxed()
});
let server = serve_with_rpc(io);
@ -68,7 +68,6 @@ fn should_extract_metadata() {
POST /rpc/ HTTP/1.1\r\n\
Host: 127.0.0.1:8080\r\n\
Connection: close\r\n\
Origin: https://parity.io/\r\n\
X-Parity-Origin: https://this.should.be.ignored\r\n\
Content-Type: application/json\r\n\
Content-Length: {}\r\n\

View File

@ -44,10 +44,7 @@ ethcore-stratum = { path = "../stratum" }
ethcore-bloom-journal = { path = "../util/bloom" }
hardware-wallet = { path = "../hw" }
stats = { path = "../util/stats" }
[dependencies.hyper]
git = "https://github.com/ethcore/hyper"
default-features = false
hyper = { git = "https://github.com/paritytech/hyper", default-features = false }
[features]
jit = ["evmjit"]

View File

@ -18,6 +18,9 @@
//! The request service is implemented using Futures. Higher level request handlers
//! will take the raw data received here and extract meaningful results from it.
// TODO [ToDr] Suppressing deprecation warnings. Rob will fix the API anyway.
#![allow(deprecated)]
use std::collections::HashMap;
use std::sync::Arc;

View File

@ -20,6 +20,7 @@ pub mod errors;
pub mod block_import;
pub mod dispatch;
pub mod informant;
pub mod oneshot;
mod network_settings;
mod poll_manager;

View File

@ -0,0 +1,67 @@
// 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 jsonrpc_core::Error;
use futures::{self, Future};
use futures::sync::oneshot;
use v1::helpers::errors;
pub type Res<T> = Result<T, Error>;
pub struct Sender<T> {
sender: oneshot::Sender<Res<T>>,
}
impl<T> Sender<T> {
pub fn send(self, data: Res<T>) {
let res = self.sender.send(data);
if let Err(_) = res {
debug!(target: "rpc", "Responding to a no longer active request.");
}
}
}
pub struct Receiver<T> {
receiver: oneshot::Receiver<Res<T>>,
}
impl<T> Future for Receiver<T> {
type Item = T;
type Error = Error;
fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
let res = self.receiver.poll();
match res {
Ok(futures::Async::NotReady) => Ok(futures::Async::NotReady),
Ok(futures::Async::Ready(Ok(res))) => Ok(futures::Async::Ready(res)),
Ok(futures::Async::Ready(Err(err))) => Err(err),
Err(e) => {
debug!(target: "rpc", "Responding to a canceled request: {:?}", e);
Err(errors::internal("Request was canceled by client.", e))
},
}
}
}
pub fn oneshot<T>() -> (Sender<T>, Receiver<T>) {
let (tx, rx) = futures::oneshot();
(Sender {
sender: tx,
}, Receiver {
receiver: rx,
})
}

View File

@ -22,10 +22,10 @@ use util::{U256, Mutex};
use ethcore::account_provider::AccountProvider;
use futures::{self, future, BoxFuture, Future};
use futures::{future, BoxFuture, Future};
use jsonrpc_core::Error;
use v1::helpers::{
errors,
errors, oneshot,
DefaultAccount,
SigningQueue, ConfirmationPromise, ConfirmationResult, SignerService
};
@ -167,21 +167,20 @@ impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
meta.origin,
);
let (ready, p) = futures::oneshot();
let (ready, p) = oneshot::oneshot();
// when dispatch is complete
res.then(move |res| {
// register callback via the oneshot sender.
handle_dispatch(res, move |response| {
match response {
Ok(RpcConfirmationResponse::Decrypt(data)) => ready.complete(Ok(data)),
Err(e) => ready.complete(Err(e)),
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
Ok(RpcConfirmationResponse::Decrypt(data)) => ready.send(Ok(data)),
Err(e) => ready.send(Err(e)),
e => ready.send(Err(errors::internal("Unexpected result.", e))),
}
});
// and wait for that to resolve.
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled.")))
p
}).boxed()
}
}
@ -196,18 +195,18 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
meta.origin,
);
let (ready, p) = futures::oneshot();
let (ready, p) = oneshot::oneshot();
res.then(move |res| {
handle_dispatch(res, move |response| {
ignore_error(match response {
Ok(RpcConfirmationResponse::Signature(sig)) => ready.complete(Ok(sig)),
Err(e) => ready.complete(Err(e)),
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
})
match response {
Ok(RpcConfirmationResponse::Signature(sig)) => ready.send(Ok(sig)),
Err(e) => ready.send(Err(e)),
e => ready.send(Err(errors::internal("Unexpected result.", e))),
}
});
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled.")))
p
}).boxed()
}
@ -218,18 +217,18 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
meta.origin,
);
let (ready, p) = futures::oneshot();
let (ready, p) = oneshot::oneshot();
res.then(move |res| {
handle_dispatch(res, move |response| {
ignore_error(match response {
Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.complete(Ok(hash)),
Err(e) => ready.complete(Err(e)),
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
})
match response {
Ok(RpcConfirmationResponse::SendTransaction(hash)) => ready.send(Ok(hash)),
Err(e) => ready.send(Err(e)),
e => ready.send(Err(errors::internal("Unexpected result.", e))),
}
});
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled.")))
p
}).boxed()
}
@ -240,18 +239,18 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
meta.origin,
);
let (ready, p) = futures::oneshot();
let (ready, p) = oneshot::oneshot();
res.then(move |res| {
handle_dispatch(res, move |response| {
ignore_error(match response {
Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.complete(Ok(tx)),
Err(e) => ready.complete(Err(e)),
e => ready.complete(Err(errors::internal("Unexpected result.", e))),
})
match response {
Ok(RpcConfirmationResponse::SignTransaction(tx)) => ready.send(Ok(tx)),
Err(e) => ready.send(Err(e)),
e => ready.send(Err(errors::internal("Unexpected result.", e))),
}
});
p.then(|result| futures::done(result.expect("Ready is never dropped nor canceled.")))
p
}).boxed()
}
}

View File

@ -35,7 +35,7 @@ impl Fetch for TestFetch {
let (tx, rx) = futures::oneshot();
thread::spawn(move || {
let cursor = io::Cursor::new(b"Some content");
tx.complete(fetch::Response::from_reader(cursor));
tx.send(fetch::Response::from_reader(cursor)).unwrap();
});
rx.map_err(|_| fetch::Error::Aborted).boxed()