【问题标题】:How to do an HTTP2 request with H2 using the new async-await syntax in Rust?如何使用 Rust 中新的 async-await 语法使用 H2 执行 HTTP2 请求?
【发布时间】:2019-08-01 11:21:17
【问题描述】:

我遇到的问题是我尝试使用 Rust 的新 async-await 语法将 H2 Akamai example 转换为代码。

我已经能够生成以下代码,但它挂在let response = response.compat().await; 上,我无法理解为什么。

#![feature(async_await)]

use tokio::net::TcpStream;
use std::sync::Arc;
use webpki::DNSNameRef;
use futures::compat::Future01CompatExt;
use futures::future::{FutureExt, TryFutureExt};
use h2::client;
use rustls::ClientConfig;
use tokio_rustls::ClientConfigExt;

use rustls::Session;

use std::net::ToSocketAddrs;
use hyper::{Method, Request};

pub fn setup_config() -> Arc<ClientConfig>
{
    std::sync::Arc::new({
        let mut c = rustls::ClientConfig::new();
        c.root_store
            .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
        c.alpn_protocols.push("h2".to_owned());
        c
    })
}

pub async fn worker()
{
    // Set the address to run our socket on.
    let address = "http2.akamai.com:443"
        .to_socket_addrs()
        .unwrap()
        .next()
        .unwrap();

    let config = setup_config();

    let dns_name = DNSNameRef::try_from_ascii_str("http2.akamai.com").unwrap();

    // Open a TCP connection.
    let tcp = TcpStream::connect(&address).compat().await.unwrap();
    ;

    let tls = config.connect_async(dns_name, tcp).compat().await.unwrap();

    let (_, session) = tls.get_ref();
    let negotiated_protocol = session.get_alpn_protocol();
    assert_eq!(Some("h2"), negotiated_protocol.as_ref().map(|x| &**x));

    let res = client::handshake(tls).compat().await;

    let (client, h2) = res.unwrap();

    println!("Test5");
    let request = Request::builder()
        .method(Method::GET)
        .uri("https://http2.akamai.com/")
        .body(())
        .unwrap();

    println!("Test6");

    let (response, x) = client.ready().compat().await.unwrap().send_request(request, true).unwrap();
    println!("Test7");

    let response = response.compat().await;
    println!("Test8");
}

fn main()
{
    // Call our `run_server` function, which returns a future.
    // As with every `async fn`, for `run_server` to do anything,
    // the returned future needs to be run. Additionally,
    // we need to convert the returned future from a futures 0.3 future into a
    // futures 0.1 future.
    let futures_03_future = worker();
    let futures_01_future = futures_03_future.unit_error().boxed().compat();

    // Finally, we can run the future to completion using the `run` function
    // provided by Hyper.
    tokio::run(futures_01_future);
}

Cargo.toml:

[dependencies]
# The latest version of the "futures" library, which has lots of utilities
# for writing async code. Enable the "compat" feature to include the
# functions for using futures 0.3 and async/await with the Hyper library,
# which use futures 0.1.
futures-preview = { version = "=0.3.0-alpha.16", features = ["compat"] }

# Hyper is an asynchronous HTTP library. We'll use it to power our HTTP
# server and to make HTTP requests.
hyper = "0.12.9"

# Tokio
tokio = "0.1.22"
h2 = "0.1.26"

# RustTLS
rustls = "0.12"
tokio-rustls = "0.5.0"
webpki = "0.18"
webpki-roots = "0.14"

输出:

Test5
Test6
Test7

我希望您能够帮助我了解为什么它在此请求期间挂起。

编辑:我也检查了 Wireshark,并且 HTTP2 连接已打开,但连接内的请求未发送。但我还是不明白为什么。

【问题讨论】:

    标签: async-await rust http2 rust-tokio hyper


    【解决方案1】:

    我也忘了在新线程上生成连接:

    tokio::spawn(h2.map_err(|_| panic!("connection failed")));
    

    欲了解更多信息,请参阅:

    https://github.com/hyperium/h2/issues/390

    https://github.com/hyperium/h2/issues/391

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      • 2018-01-28
      相关资源
      最近更新 更多