使用Hyper HTTP Client实施重试

时间:2017-07-05 22:07:15

标签: rust hyper rust-tokio

我尝试在使用 Hyper v0.11 构建的客户端中实现重试,但我无法找到重用不同尝试请求的方法:

#[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

错误很明显,但我不知道如何修复它。

2 个答案:

答案 0 :(得分:0)

一种选择是使用tokio-retry条板箱。我只尝试了超级v0.12。

答案 1 :(得分:-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
    }
}