2017-07-05 4 views
1

で再試行実装します私は<em>ハイパーv0.11</em>で構築されたクライアントでの再試行を実施しようとしているが、私は別の試みのために要求を再利用する方法を見つけることができませんハイパーHTTPクライアント

#[macro_use] 
extern crate hyper; 
extern crate futures; 
extern crate tokio_core; 

use futures::Future; 

use hyper::{Client, Body, Uri, StatusCode}; 
use hyper::server::{Request, Response}; 
use hyper::client::HttpConnector; 
use hyper::Get; 

use tokio_core::reactor::Core; 

fn main() { 

    let mut core = Core::new().expect("Event Loop"); 
    let handle = core.handle(); 
    let client = Client::new(&handle.clone()); 

    // Request 
    let json = r#"{"user":"Peter"}"#; 
    let mut req: Request<Body> = Request::new(Post, "http://localhost:8080/create/user".parse().unwrap()); 
    req.headers_mut().set(ContentType::json()); 
    req.headers_mut().set(ContentLength(json.len() as u64)); 
    req.set_body(json); 

    dispatch_request(&client, req, 2); 
} 

fn clone_req(req: &Request) -> Request { 
    let mut new_req = Request::new(req.method().clone(), req.uri().clone()); 
    new_req.headers_mut().extend(req.headers().iter()); 
    new_req.set_body(req.body()); // <------- here the error occur! 
    new_req 
} 

fn dispatch_request(
    client: &Client<HttpConnector, Body>, 
    req: Request<Body>, 
    n_retry: u32, 
) -> Box<Future<Error = hyper::Error, Item = Response>> { 
    println!("Attemp {}", n_retry); 
    let max_retry = 3; 

    let client_clone = client.clone(); 

    let clone_req = clone_req(&req); 

    let resp = client.request(req).then(move |result| match result { 
     Ok(client_resp) => { 
      if client_resp.status() == hyper::StatusCode::Ok { 
       Box::new(futures::future::ok(client_resp)) 
      } else if n_retry < max_retry { 
       dispatch_request(&client_clone, clone_req, max_retry + 1) 
      } else { 
       Box::new(futures::future::ok(
        Response::new().with_status(StatusCode::ServiceUnavailable), 
       )) 
      } 
     } 
     Err(e) => { 
      println!("Connection error: {:?}", &e); 
      Box::new(futures::future::ok(
       Response::new().with_status(StatusCode::ServiceUnavailable), 
      )) 
     } 
    }); 
    Box::new(resp) 
} 

これは、コンパイル・エラーです:

error[E0507]: cannot move out of borrowed content 
    --> src/main.rs:28:22 
    | 
28 |  new_req.set_body(req.body()); 
    |      ^^^ cannot move out of borrowed content 

エラーがクリアされているが、私はそれを修正する方法がわかりません。

+0

bodyがストリームなので、bodyをコピーできるかどうかはわかりません。 – Stargateur

+0

リクエスト本体を 'body()'とするには、リクエストを所有している必要がありますが、 'clone_req'には参照のみがあります。 [同じエラーメッセージを持つ既存の質問](https://stackoverflow.com/search?q=%5Brust%5D+cannot+move+out+of+borrowed+content)に目を通したことがありますか?あなたが間違っていることについての洞察? –

+0

@ E_net4はい、私はいくつかの回避策を探して、他の変数にボディー(ストリームのような)を書き込もうとする例を見ていましたが、修正できませんでした。 – cspinetta

答えて

-1

なぜメインループに再試行しますか?また、どこかでcore.runを実行する必要があることに注意してください。

loop { 
    let req = Request::new(Get, "http://www.google.com".parse().unwrap()); 
    let resp = dispatch_request(&client, req,); 
    if let Ok(_) = resp.wait() { 
     break 
    } 
} 
+0

お返事ありがとうございます!しかし、あなたの提案は、私が必要とする機能性をカバーするのに十分ではありません。 **すべてのタイプのリクエスト**のために用意された再試行スキームが必要です。また、リクエストは外部から与えられます。なぜなら、プロキシだからです。私は到来するリクエストを新着リクエストに伝播する方法が必要です(着信に似ていますが、他のホストと同様です)、問題はボディを伝播する方法です(理想的には.concat()を使用せずに潜在的に適切な方法でチャンクストリーム) – cspinetta

関連する問題