From 586bb1023ad37414b2a2f8371fcb9927ace3f815 Mon Sep 17 00:00:00 2001 From: Andrew Straw Date: Wed, 25 Apr 2018 06:07:03 -0700 Subject: [PATCH] remove use of futures and tokio from within client This removes an invalid use of futures: previously, the client would create its own instance of a tokio_core reactor core and synchronously block on this core while waiting for a response. With recent releases of futures, this results in the error "cannot recursively call into `Core`". This is discussed at https://github.com/tokio-rs/tokio-core/issues/319 and was apparently never correct behavior. To solve the problem and continue to use futures, it would be necessary to allow the client to spawn new futures on an existing executor. However, because the futures API is in flux right now and the current behavior was simply to block synchronously on the response anyway, I simply reverted the use of hyper to an older, pre-futures version and kept the public API of xml-rpc unchanged. In the future (e.g. once the futures ecosystem has settled down), it would be good to remove the blocking wait, but for now this works for me. --- Cargo.toml | 2 +- hyper10/Cargo.toml | 7 +++++++ hyper10/src/lib.rs | 2 ++ src/client.rs | 44 ++++++++++++++++++++++---------------------- src/lib.rs | 3 ++- 5 files changed, 34 insertions(+), 24 deletions(-) create mode 100644 hyper10/Cargo.toml create mode 100644 hyper10/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 1ca326a..07ef935 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ version = "0.0.8" base64 = "0.6.0" error-chain = "0.10.0" futures = "0.1.14" +hyper10 = {path="hyper10"} hyper = "0.11.2" lazy_static = "1.0.0" regex = "0.2.3" @@ -18,5 +19,4 @@ serde = "1.0.11" serde-xml-rs = "0.2.1" serde_bytes = "0.10.2" serde_derive = "1.0.11" -tokio-core = "0.1.9" xml-rs = "0.6.1" diff --git a/hyper10/Cargo.toml b/hyper10/Cargo.toml new file mode 100644 index 0000000..24ba2bd --- /dev/null +++ b/hyper10/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "hyper10" +version = "0.1.0" +authors = ["Andrew Straw "] + +[dependencies] +hyper = "0.10" diff --git a/hyper10/src/lib.rs b/hyper10/src/lib.rs new file mode 100644 index 0000000..52373f1 --- /dev/null +++ b/hyper10/src/lib.rs @@ -0,0 +1,2 @@ +extern crate hyper; +pub use hyper::*; diff --git a/src/client.rs b/src/client.rs index b405a1e..446681f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,11 +1,13 @@ use std; -use futures::{Future, Stream}; -use hyper::{self, Client as HyperClient, Method, Request, Uri}; +use hyper::Uri; +use hyper10::{self, Client as HyperClient}; use serde::{Deserialize, Serialize}; -use tokio_core::reactor::Core; use super::error::{Result, ResultExt}; use super::xmlfmt::{from_params, into_params, parse, Call, Fault, Params, Response}; +use hyper10::header::Headers; +header! { (ContentType, "ContentType") => [String] } + pub fn call_value(uri: &Uri, name: Tkey, params: Params) -> Result where Tkey: Into, @@ -27,16 +29,13 @@ where } pub struct Client { - core: Core, - client: HyperClient, + client: HyperClient, } impl Client { pub fn new() -> Result { - let core = Core::new().chain_err(|| "Failed to initialize Tokio Core.")?; - let client = HyperClient::new(&core.handle()); + let client = HyperClient::new(); Ok(Client { - core: core, client: client, }) } @@ -46,23 +45,24 @@ impl Client { Tkey: Into, { use super::xmlfmt::value::ToXml; - let body = Call { + let body_str = Call { name: name.into(), params, }.to_xml(); - let mut request = Request::new(Method::Post, uri.clone()); - request - .headers_mut() - .set(hyper::header::ContentLength(body.len() as u64)); - request.headers_mut().set(hyper::header::ContentType::xml()); - request.set_body(body); - let work = self.client - .request(request) - .and_then(|res| res.body().concat2().map(|chunk| chunk.to_vec())); - let response = self.core - .run(work) - .chain_err(|| "Failed to run the HTTP request within Tokio Core.")?; - parse::response(response.as_slice()).map_err(Into::into) + let bytes: &[u8] = body_str.as_bytes(); + let body = hyper10::client::Body::BufBody(bytes, bytes.len()); + + let mut headers = Headers::new(); + headers.set(ContentType("xml".to_owned())); + + let response = self.client + .post(uri.as_ref()) + .headers(headers) + .body(body) + .send() + .chain_err(|| "Failed to run the HTTP request within hyper.")?; + + parse::response(response).map_err(Into::into) } pub fn call<'a, Tkey, Treq, Tres>( diff --git a/src/lib.rs b/src/lib.rs index 16abe0d..c26d318 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,8 @@ extern crate base64; #[macro_use] extern crate error_chain; extern crate futures; +#[macro_use] +extern crate hyper10; extern crate hyper; #[macro_use] extern crate lazy_static; @@ -15,7 +17,6 @@ extern crate serde_bytes; #[macro_use] extern crate serde_derive; extern crate serde_xml_rs; -extern crate tokio_core; extern crate xml; pub mod client;