|  | 
| 1 |  | -use std::env; | 
|  | 1 | +use tower::ServiceExt; | 
|  | 2 | +use tower_service::Service; | 
| 2 | 3 | 
 | 
| 3 |  | -use http_body_util::Empty; | 
| 4 |  | -use hyper::Request; | 
| 5 |  | -use hyper_util::client::legacy::{connect::HttpConnector, Client}; | 
|  | 4 | +use hyper_util::client::pool; | 
| 6 | 5 | 
 | 
| 7 | 6 | #[tokio::main(flavor = "current_thread")] | 
| 8 |  | -async fn main() -> Result<(), Box<dyn std::error::Error>> { | 
| 9 |  | - let url = match env::args().nth(1) { | 
| 10 |  | - Some(url) => url, | 
| 11 |  | - None => { | 
| 12 |  | - eprintln!("Usage: client <url>"); | 
| 13 |  | - return Ok(()); | 
| 14 |  | - } | 
| 15 |  | - }; | 
| 16 |  | - | 
| 17 |  | - // HTTPS requires picking a TLS implementation, so give a better | 
| 18 |  | - // warning if the user tries to request an 'https' URL. | 
| 19 |  | - let url = url.parse::<hyper::Uri>()?; | 
| 20 |  | - if url.scheme_str() != Some("http") { | 
| 21 |  | - eprintln!("This example only works with 'http' URLs."); | 
| 22 |  | - return Ok(()); | 
|  | 7 | +async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { | 
|  | 8 | + send_nego().await | 
|  | 9 | +} | 
|  | 10 | + | 
|  | 11 | +async fn send_h1() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { | 
|  | 12 | + let tcp = hyper_util::client::legacy::connect::HttpConnector::new(); | 
|  | 13 | + | 
|  | 14 | + let http1 = tcp.and_then(|conn| { | 
|  | 15 | + Box::pin(async move { | 
|  | 16 | + let (mut tx, c) = hyper::client::conn::http1::handshake::< | 
|  | 17 | + _, | 
|  | 18 | + http_body_util::Empty<hyper::body::Bytes>, | 
|  | 19 | + >(conn) | 
|  | 20 | + .await?; | 
|  | 21 | + tokio::spawn(async move { | 
|  | 22 | + if let Err(e) = c.await { | 
|  | 23 | + eprintln!("connection error: {:?}", e); | 
|  | 24 | + } | 
|  | 25 | + }); | 
|  | 26 | + let svc = tower::service_fn(move |req| tx.send_request(req)); | 
|  | 27 | + Ok::<_, Box<dyn std::error::Error + Send + Sync>>(svc) | 
|  | 28 | + }) | 
|  | 29 | + }); | 
|  | 30 | + | 
|  | 31 | + let mut p = pool::Cache::new(http1).build(); | 
|  | 32 | + | 
|  | 33 | + let mut c = p.call(http::Uri::from_static("http://hyper.rs")).await?; | 
|  | 34 | + eprintln!("{:?}", c); | 
|  | 35 | + | 
|  | 36 | + let req = http::Request::builder() | 
|  | 37 | + .header("host", "hyper.rs") | 
|  | 38 | + .body(http_body_util::Empty::new()) | 
|  | 39 | + .unwrap(); | 
|  | 40 | + | 
|  | 41 | + c.ready().await?; | 
|  | 42 | + let resp = c.call(req).await?; | 
|  | 43 | + eprintln!("{:?}", resp); | 
|  | 44 | + | 
|  | 45 | + Ok(()) | 
|  | 46 | +} | 
|  | 47 | + | 
|  | 48 | +async fn send_h2() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { | 
|  | 49 | + let tcp = hyper_util::client::legacy::connect::HttpConnector::new(); | 
|  | 50 | + | 
|  | 51 | + let http2 = tcp.and_then(|conn| { | 
|  | 52 | + Box::pin(async move { | 
|  | 53 | + let (mut tx, c) = hyper::client::conn::http2::handshake::< | 
|  | 54 | + _, | 
|  | 55 | + _, | 
|  | 56 | + http_body_util::Empty<hyper::body::Bytes>, | 
|  | 57 | + >(hyper_util::rt::TokioExecutor::new(), conn) | 
|  | 58 | + .await?; | 
|  | 59 | + println!("connected"); | 
|  | 60 | + tokio::spawn(async move { | 
|  | 61 | + if let Err(e) = c.await { | 
|  | 62 | + eprintln!("connection error: {:?}", e); | 
|  | 63 | + } | 
|  | 64 | + }); | 
|  | 65 | + let svc = tower::service_fn(move |req| tx.send_request(req)); | 
|  | 66 | + Ok::<_, Box<dyn std::error::Error + Send + Sync>>(svc) | 
|  | 67 | + }) | 
|  | 68 | + }); | 
|  | 69 | + | 
|  | 70 | + let mut p = pool::Singleton::new(http2); | 
|  | 71 | + | 
|  | 72 | + for _ in 0..5 { | 
|  | 73 | + let mut c = p | 
|  | 74 | + .call(http::Uri::from_static("http://localhost:3000")) | 
|  | 75 | + .await?; | 
|  | 76 | + eprintln!("{:?}", c); | 
|  | 77 | + | 
|  | 78 | + let req = http::Request::builder() | 
|  | 79 | + .header("host", "hyper.rs") | 
|  | 80 | + .body(http_body_util::Empty::new()) | 
|  | 81 | + .unwrap(); | 
|  | 82 | + | 
|  | 83 | + c.ready().await?; | 
|  | 84 | + let resp = c.call(req).await?; | 
|  | 85 | + eprintln!("{:?}", resp); | 
| 23 | 86 |  } | 
| 24 | 87 | 
 | 
| 25 |  | - let client = Client::builder(hyper_util::rt::TokioExecutor::new()).build(HttpConnector::new()); | 
|  | 88 | + Ok(()) | 
|  | 89 | +} | 
| 26 | 90 | 
 | 
| 27 |  | - let req = Request::builder() | 
| 28 |  | - .uri(url) | 
| 29 |  | - .body(Empty::<bytes::Bytes>::new())?; | 
|  | 91 | +async fn send_nego() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { | 
|  | 92 | + let tcp = hyper_util::client::legacy::connect::HttpConnector::new(); | 
| 30 | 93 | 
 | 
| 31 |  | - let resp = client.request(req).await?; | 
|  | 94 | + let http1 = tower::layer::layer_fn(|tcp| { | 
|  | 95 | + tower::service_fn(move |dst| { | 
|  | 96 | + let inner = tcp.call(dst); | 
|  | 97 | + async move { | 
|  | 98 | + let conn = inner.await?; | 
|  | 99 | + let (mut tx, c) = hyper::client::conn::http1::handshake::< | 
|  | 100 | + _, | 
|  | 101 | + http_body_util::Empty<hyper::body::Bytes>, | 
|  | 102 | + >(conn) | 
|  | 103 | + .await?; | 
|  | 104 | + tokio::spawn(async move { | 
|  | 105 | + if let Err(e) = c.await { | 
|  | 106 | + eprintln!("connection error: {:?}", e); | 
|  | 107 | + } | 
|  | 108 | + }); | 
|  | 109 | + let svc = tower::service_fn(move |req| tx.send_request(req)); | 
|  | 110 | + Ok::<_, Box<dyn std::error::Error + Send + Sync>>(svc) | 
|  | 111 | + } | 
|  | 112 | + }) | 
|  | 113 | + }); | 
| 32 | 114 | 
 | 
| 33 |  | - eprintln!("{:?} {:?}", resp.version(), resp.status()); | 
| 34 |  | - eprintln!("{:#?}", resp.headers()); | 
|  | 115 | + let http2 = tower::layer::layer_fn(|tcp| { | 
|  | 116 | + tower::service_fn(move |dst| { | 
|  | 117 | + let inner = tcp.call(dst); | 
|  | 118 | + async move { | 
|  | 119 | + let conn = inner.await?; | 
|  | 120 | + let (mut tx, c) = hyper::client::conn::http2::handshake::< | 
|  | 121 | + _, | 
|  | 122 | + _, | 
|  | 123 | + http_body_util::Empty<hyper::body::Bytes>, | 
|  | 124 | + >(hyper_util::rt::TokioExecutor::new(), conn) | 
|  | 125 | + .await?; | 
|  | 126 | + println!("connected"); | 
|  | 127 | + tokio::spawn(async move { | 
|  | 128 | + if let Err(e) = c.await { | 
|  | 129 | + eprintln!("connection error: {:?}", e); | 
|  | 130 | + } | 
|  | 131 | + }); | 
|  | 132 | + let svc = tower::service_fn(move |req| tx.send_request(req)); | 
|  | 133 | + Ok::<_, Box<dyn std::error::Error + Send + Sync>>(svc) | 
|  | 134 | + } | 
|  | 135 | + }) | 
|  | 136 | + }); | 
|  | 137 | + | 
|  | 138 | + let mut svc = pool::negotiate(tcp, |_| false, http1, http2); | 
|  | 139 | + | 
|  | 140 | + for _ in 0..5 { | 
|  | 141 | + let mut c = svc | 
|  | 142 | + .call(http::Uri::from_static("http://localhost:3000")) | 
|  | 143 | + .await?; | 
|  | 144 | + eprintln!("{:?}", c); | 
|  | 145 | + | 
|  | 146 | + let req = http::Request::builder() | 
|  | 147 | + .header("host", "hyper.rs") | 
|  | 148 | + .body(http_body_util::Empty::new()) | 
|  | 149 | + .unwrap(); | 
|  | 150 | + | 
|  | 151 | + c.ready().await?; | 
|  | 152 | + let resp = c.call(req).await?; | 
|  | 153 | + eprintln!("{:?}", resp); | 
|  | 154 | + } | 
| 35 | 155 | 
 | 
| 36 | 156 |  Ok(()) | 
| 37 | 157 | } | 
0 commit comments