【问题标题】:How to set timeout for HTTP request with hyper, tokio and futures in Rust?如何在 Rust 中使用 hyper、tokio 和 futures 为 HTTP 请求设置超时?
【发布时间】:2017-12-31 23:01:55
【问题描述】:

如何使用异步 Hyper (>= 0.11) 为 HTTP 请求设置超时?

这里是没有超时的代码示例:

extern crate hyper;
extern crate tokio_core;
extern crate futures;

use futures::Future;
use hyper::Client;
use tokio_core::reactor::Core;

fn main() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());

    let uri = "http://stackoverflow.com".parse().unwrap();
    let work = client.get(uri).map(|res| {
        res.status()
    });

    match core.run(work) {
        Ok(status) => println!("Status: {}", status),
        Err(e) => println!("Error: {:?}", e)
    }
}

【问题讨论】:

    标签: http rust timeout hyper rust-tokio


    【解决方案1】:

    根据 seanmonstar 提供的指向Hyper Guide / General Timeout 的链接,用一个工作代码示例回答我自己的问题:

    extern crate hyper;
    extern crate tokio_core;
    extern crate futures;
    
    use futures::Future;
    use futures::future::Either;
    use hyper::Client;
    use tokio_core::reactor::Core;
    use std::time::Duration;
    use std::io;
    
    fn main() {
        let mut core = Core::new().unwrap();
        let handle = core.handle();
        let client = Client::new(&handle);
    
        let uri: hyper::Uri = "http://stackoverflow.com".parse().unwrap();
        let request = client.get(uri.clone()).map(|res| res.status());
    
        let timeout = tokio_core::reactor::Timeout::new(Duration::from_millis(170), &handle).unwrap();
    
        let work = request.select2(timeout).then(|res| match res {
            Ok(Either::A((got, _timeout))) => Ok(got),
            Ok(Either::B((_timeout_error, _get))) => {
                Err(hyper::Error::Io(io::Error::new(
                    io::ErrorKind::TimedOut,
                    "Client timed out while connecting",
                )))
            }
            Err(Either::A((get_error, _timeout))) => Err(get_error),
            Err(Either::B((timeout_error, _get))) => Err(From::from(timeout_error)),
        });
    
        match core.run(work) {
            Ok(status) => println!("OK: {:?}", status),
            Err(e) => println!("Error: {:?}", e)
        }
    }
    

    【讨论】:

      【解决方案2】:

      仅供参考,Tokyo >= 1.0 让这变得容易多了,因为他们现在有一个专用的 timeout 包装器,可以应用于未来(例如请求),并将原始未来类型包装在 @ 987654322@,其Ok 是原始未来类型,其Err 是超时错误。

      因此,您在问题中的代码现在可以按如下方式处理超时:

      extern crate tokio; // 1.7.1, full features
      
      use hyper::Client;
      use std::time::Duration;
      
      #[tokio::main]
      async fn main() {
          let client = Client::new();
      
      
          let uri = "http://stackoverflow.com".parse().unwrap();
          let work = client.get(uri);
      
          match tokio::time::timeout(Duration::from_millis(10), work).await {
              Ok(result) => match result {
                  Ok(response) => println!("Status: {}", response.status()),
                  Err(e) => println!("Network error: {:?}", e),
              },
              Err(_) => println!("Timeout: no response in 10 milliseconds."),
          };
      }
      

      (当然,这段代码总会给你一个超时时间。要查看来自网络的预期 301 响应,请尝试设置为 200 毫秒。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-20
        • 2017-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-01
        • 2017-05-18
        相关资源
        最近更新 更多