Skip to content

Commit 41e676b

Browse files
committed
Bump hyper version to 1.0
Signed-off-by: csh <458761603@qq.com>
1 parent 2dc4198 commit 41e676b

9 files changed

Lines changed: 631 additions & 101 deletions

File tree

.cargo/config.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[build]
2-
target="wasm32-wasi"
2+
target = "wasm32-wasi"
3+
rustflags = "--cfg tokio_unstable"
34

45
[target.wasm32-wasi]
5-
runner = "wasmedge"
6+
runner = "wasmedge"

client-https/Cargo.toml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
hyper_wasi = { version = "0.15", features = ["full"]}
10-
http-body-util = "0.1.0-rc.2"
11-
tokio_wasi = { version = "1", features = ["rt", "macros", "net", "time", "io-util"]}
9+
hyper = { version = "1", features = ["full"] }
10+
tokio = { version = "1", features = ["rt", "macros", "net", "time", "io-util"] }
1211
pretty_env_logger = "0.4.0"
13-
wasmedge_rustls_api = { version = "0.1", features = [ "tokio_async" ] }
14-
wasmedge_hyper_rustls = "0.1.0"
12+
13+
wasmedge_wasi_socket = "0.5"
14+
pin-project = "1.1.3"
15+
http-body-util = "0.1.0"
16+
17+
tokio-rustls = "0.25.0"
18+
webpki-roots = "0.26.0"
19+
rustls = "0.22.2"

client-https/src/main.rs

Lines changed: 148 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,165 @@
1-
use hyper::Client;
1+
#![deny(warnings)]
2+
#![warn(rust_2018_idioms)]
23

3-
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
4+
// use tokio::io::{self, AsyncWriteExt as _};
5+
6+
use std::{
7+
os::fd::{FromRawFd, IntoRawFd},
8+
pin::Pin,
9+
sync::Arc,
10+
task::{Context, Poll},
11+
};
12+
13+
use http_body_util::{BodyExt, Empty};
14+
use hyper::{body::Bytes, Request};
15+
16+
use rustls::pki_types::ServerName;
17+
use tokio::net::TcpStream;
18+
19+
type MainResult<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
420

521
#[tokio::main(flavor = "current_thread")]
6-
async fn main() {
22+
async fn main() -> MainResult<()> {
23+
pretty_env_logger::init();
24+
725
let url = "https://httpbin.org/get?msg=WasmEdge"
826
.parse::<hyper::Uri>()
927
.unwrap();
10-
fetch_https_url(url).await.unwrap();
28+
fetch_https_url(url).await
29+
}
30+
31+
use pin_project::pin_project;
32+
use tokio_rustls::TlsConnector;
33+
34+
#[pin_project]
35+
#[derive(Debug)]
36+
struct TokioIo<T> {
37+
#[pin]
38+
inner: T,
39+
}
40+
41+
impl<T> TokioIo<T> {
42+
pub fn new(inner: T) -> Self {
43+
Self { inner }
44+
}
45+
46+
#[allow(dead_code)]
47+
pub fn inner(self) -> T {
48+
self.inner
49+
}
50+
}
51+
52+
impl<T> hyper::rt::Read for TokioIo<T>
53+
where
54+
T: tokio::io::AsyncRead,
55+
{
56+
fn poll_read(
57+
self: std::pin::Pin<&mut Self>,
58+
cx: &mut std::task::Context<'_>,
59+
mut buf: hyper::rt::ReadBufCursor<'_>,
60+
) -> std::task::Poll<Result<(), std::io::Error>> {
61+
let n = unsafe {
62+
let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut());
63+
match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) {
64+
Poll::Ready(Ok(())) => tbuf.filled().len(),
65+
other => return other,
66+
}
67+
};
68+
69+
unsafe {
70+
buf.advance(n);
71+
}
72+
Poll::Ready(Ok(()))
73+
}
1174
}
1275

13-
async fn fetch_https_url(url: hyper::Uri) -> Result<()> {
14-
let https = wasmedge_hyper_rustls::connector::new_https_connector(
15-
wasmedge_rustls_api::ClientConfig::default(),
16-
);
17-
let client = Client::builder().build::<_, hyper::Body>(https);
76+
impl<T> hyper::rt::Write for TokioIo<T>
77+
where
78+
T: tokio::io::AsyncWrite,
79+
{
80+
fn poll_write(
81+
self: Pin<&mut Self>,
82+
cx: &mut Context<'_>,
83+
buf: &[u8],
84+
) -> Poll<Result<usize, std::io::Error>> {
85+
tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf)
86+
}
87+
88+
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
89+
tokio::io::AsyncWrite::poll_flush(self.project().inner, cx)
90+
}
91+
92+
fn poll_shutdown(
93+
self: Pin<&mut Self>,
94+
cx: &mut Context<'_>,
95+
) -> Poll<Result<(), std::io::Error>> {
96+
tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx)
97+
}
98+
99+
fn is_write_vectored(&self) -> bool {
100+
tokio::io::AsyncWrite::is_write_vectored(&self.inner)
101+
}
102+
103+
fn poll_write_vectored(
104+
self: Pin<&mut Self>,
105+
cx: &mut Context<'_>,
106+
bufs: &[std::io::IoSlice<'_>],
107+
) -> Poll<std::prelude::v1::Result<usize, std::io::Error>> {
108+
tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs)
109+
}
110+
}
111+
112+
async fn fetch_https_url(url: hyper::Uri) -> MainResult<()> {
113+
let host = url.host().expect("uri has no host");
114+
let port = url.port_u16().unwrap_or(443);
115+
let addr = format!("{}:{}", host, port);
116+
117+
let mut root_store = rustls::RootCertStore::empty();
118+
root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
119+
120+
let config = rustls::ClientConfig::builder()
121+
.with_root_certificates(root_store)
122+
.with_no_client_auth();
123+
124+
let connector = TlsConnector::from(Arc::new(config));
125+
let stream = unsafe {
126+
let fd = wasmedge_wasi_socket::TcpStream::connect(addr)?.into_raw_fd();
127+
TcpStream::from_std(std::net::TcpStream::from_raw_fd(fd))?
128+
};
129+
130+
let domain = ServerName::try_from(host.to_string()).unwrap();
131+
let stream = connector.connect(domain, stream).await.unwrap();
132+
133+
let io = TokioIo::new(stream);
134+
135+
let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;
136+
tokio::task::spawn(async move {
137+
if let Err(err) = conn.await {
138+
println!("Connection failed: {:?}", err);
139+
}
140+
});
141+
142+
let authority = url.authority().unwrap().clone();
143+
144+
let req = Request::builder()
145+
.uri(url)
146+
.header(hyper::header::HOST, authority.as_str())
147+
.body(Empty::<Bytes>::new())?;
18148

19-
let res = client.get(url).await?;
149+
let mut res = sender.send_request(req).await?;
20150

21151
println!("Response: {}", res.status());
22152
println!("Headers: {:#?}\n", res.headers());
23153

24-
let body = hyper::body::to_bytes(res.into_body()).await.unwrap();
25-
println!("{}", String::from_utf8(body.into()).unwrap());
154+
let mut resp_data = Vec::new();
155+
while let Some(next) = res.frame().await {
156+
let frame = next?;
157+
if let Some(chunk) = frame.data_ref() {
158+
resp_data.extend_from_slice(&chunk);
159+
}
160+
}
26161

27-
println!("\n\nDone!");
162+
println!("{}", String::from_utf8_lossy(&resp_data));
28163

29164
Ok(())
30165
}

client/Cargo.toml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
hyper_wasi = { version = "0.15", features = ["full"] }
8-
tokio_wasi = { version = "1", features = [
9-
"rt",
10-
"macros",
11-
"net",
12-
"time",
13-
"io-util",
14-
] }
7+
hyper = { version = "1", features = ["full"] }
8+
tokio = { version = "1", features = ["rt", "macros", "net", "time", "io-util"] }
159
pretty_env_logger = "0.4.0"
10+
wasmedge_wasi_socket = "0.5"
11+
pin-project = "1.1.3"
12+
http-body-util = "0.1.0"

0 commit comments

Comments
 (0)