0

a strange problem, if get_vec param config pass from outside, test_get_vec current_thread::block_on_all will never ends and do a println. but if I reinit the config param in get_vec, current_thread::block_on_all will get the result and println. i use reqwest = { version = "0.9.24" } , tokio = "0.1", futures= "0.1"

reqwest::r#async::ClientBuilder is a async , it must call in a future?

use std::collections::HashMap;
use std::mem;
use std::str::FromStr;
use std::time::{Duration, Instant};

use block_modes::cipher::errors;
use error_chain::error_chain;
use futures::{Future, Stream};
use hyper::header::HeaderValue;
use hyper::http::response;
use reqwest::{Error, get, Url};
use reqwest::r#async::{Client, Decoder};
use reqwest::r#async::Client as HttpClient;
use reqwest::r#async::ClientBuilder;
use reqwest::r#async::RequestBuilder;
use serde::de::DeserializeOwned;
use serde_derive::{Deserialize, Serialize};
use tokio::runtime::current_thread;

use crate::test::QueryOptions;

#[derive(Clone, Debug)]
pub struct Config {
    pub address: String,
    pub datacenter: Option<String>,
    pub http_client: HttpClient,
    pub token: Option<String>,
    pub wait_time: Option<Duration>,
}

#[derive(Clone, Default, Eq, PartialEq, Serialize, Deserialize, Debug)]
pub struct KVPair {
    pub Key: String,
}


pub type ConsulGetVecFuture<R> = Box<dyn Future<Item=Result<(R), String>, Error=Error>>;


pub fn get_vec<R: DeserializeOwned + Default + 'static>(
    path: &str,
    config: &Config,
    mut params: HashMap<String, String>,
) -> Result<ConsulGetVecFuture<R>, String> {
    let url_str = format!("{}{}", config.address, path);
    let url = Url::parse_with_params(&url_str, params.iter()).unwrap();
    /*  if uncomment this block, it works, no more block
    let config = ClientBuilder::new()
        .build()
        .map(|client| Config {
            address: String::from("http://consul.test.com".to_string()),
            datacenter: None,
            http_client: client,
            token: None,
            wait_time: None,
        }).unwrap();
    */
    let request_builder = config.http_client.get(url);  // if config.http_client change to Client::new() , and it works also.
    let response = request_builder.send();
    let fu = response.and_then(|mut r| {
        r.into_body().concat2()
    })
        .and_then(|body| {
            println!("body: {:?}", body);
            Ok(body)
        })
        .map(move |body| {
            let j: R = serde_json::from_slice::<R>(&body).unwrap_or_else(|e| {
                println!("Failed to parse response: {}", e);
                R::default()
            });
            Ok(j)
        }).map_err(|err| {
            err
        });

    Ok(Box::new(fu))
}

#[test]
fn test_get_vec() {
    let mut params = HashMap::new();
    params.insert(String::from("recurse"), String::from(""));
    let path = "/xxx/infra-java-server";
    let config = ClientBuilder::new()
        .build()
        .map(|client| Config {
            address: String::from("http://consul.test.com".to_string()),
            datacenter: None,
            http_client: client,
            token: None,
            wait_time: None,
        }).unwrap();



    let kv = get_vec::<KVPair>(path, &config, params).unwrap();
    let kv = current_thread::block_on_all(kv).unwrap().unwrap();
    println!("==================ends================")

}
weizhao
  • 183
  • 3
  • 16

0 Answers0