Repository: bytecodealliance/wasmtime
Pull request #7555 (2023-11-17 16:31:01)

Update hyper dependency to stable release
This updates hyper to 1.0.0 and handles the various updates necessary along with a few other dependency updates.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 3f698546e..b2bc044fc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1306,9 +1306,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
 name = "h2"
-version = "0.3.19"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
+checksum = "e1d308f63daf4181410c242d34c11f928dcb3aa105852019e043c9d1f4e4368a"
 dependencies = [
  "bytes",
  "fnv",
@@ -1316,7 +1316,7 @@ dependencies = [
  "futures-sink",
  "futures-util",
  "http",
- "indexmap 1.9.1",
+ "indexmap 2.0.0",
  "slab",
  "tokio",
  "tokio-util",
@@ -1379,9 +1379,9 @@ checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
 
 [[package]]
 name = "http"
-version = "0.2.9"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
 dependencies = [
  "bytes",
  "fnv",
@@ -1390,9 +1390,9 @@ dependencies = [
 
 [[package]]
 name = "http-body"
-version = "1.0.0-rc.2"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "951dfc2e32ac02d67c90c0d65bd27009a635dc9b381a2cc7d284ab01e3a0150d"
+checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
 dependencies = [
  "bytes",
  "http",
@@ -1400,9 +1400,9 @@ dependencies = [
 
 [[package]]
 name = "http-body-util"
-version = "0.1.0-rc.2"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92445bc9cc14bfa0a3ce56817dc3b5bcc227a168781a356b702410789cec0d10"
+checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
 dependencies = [
  "bytes",
  "futures-util",
@@ -1440,13 +1440,12 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "hyper"
-version = "1.0.0-rc.3"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b75264b2003a3913f118d35c586e535293b3e22e41f074930762929d071e092"
+checksum = "403f9214f3e703236b221f1a9cd88ec8b4adfa5296de01ab96216361f4692f56"
 dependencies = [
  "bytes",
  "futures-channel",
- "futures-core",
  "futures-util",
  "h2",
  "http",
@@ -1456,7 +1455,6 @@ dependencies = [
  "itoa",
  "pin-project-lite",
  "tokio",
- "tracing",
  "want",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index f1835bf65..cedbac611 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -256,10 +256,10 @@ filecheck = "0.5.0"
 libc = "0.2.60"
 file-per-thread-logger = "0.2.0"
 tokio = { version = "1.26.0", features = [ "rt", "time" ] }
-hyper = "=1.0.0-rc.3"
-http = "0.2.9"
-http-body = "=1.0.0-rc.2"
-http-body-util = "=0.1.0-rc.2"
+hyper = "1.0.1"
+http = "1.0.0"
+http-body = "1.0.0"
+http-body-util = "0.1.0"
 bytes = "1.4"
 futures = { version = "0.3.27", default-features = false }
 indexmap = "2.0.0"
diff --git a/crates/wasi-http/src/io.rs b/crates/wasi-http/src/io.rs
new file mode 100644
index 000000000..e4f00079e
--- /dev/null
+++ b/crates/wasi-http/src/io.rs
@@ -0,0 +1,50 @@
+use hyper::rt::{Read, ReadBufCursor, Write};
+use std::io::Error;
+use std::marker::Unpin;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
+
+pub struct TokioIo<T> {
+    inner: T,
+}
+
+impl<T> TokioIo<T> {
+    pub fn new(inner: T) -> TokioIo<T> {
+        TokioIo { inner }
+    }
+}
+
+impl<T: AsyncRead + Unpin> Read for TokioIo<T> {
+    fn poll_read(
+        mut self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        mut buf: ReadBufCursor<'_>,
+    ) -> Poll<Result<(), Error>> {
+        unsafe {
+            let mut dst = ReadBuf::uninit(buf.as_mut());
+            let res = Pin::new(&mut self.inner).poll_read(cx, &mut dst);
+            let amt = dst.filled().len();
+            buf.advance(amt);
+            res
+        }
+    }
+}
+
+impl<T: AsyncWrite + Unpin> Write for TokioIo<T> {
+    fn poll_write(
+        mut self: Pin<&mut Self>,
+        cx: &mut Context<'_>,
+        buf: &[u8],
+    ) -> Poll<Result<usize, Error>> {
+        Pin::new(&mut self.inner).poll_write(cx, buf)
+    }
+
+    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
+        Pin::new(&mut self.inner).poll_flush(cx)
+    }
+
+    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
+        Pin::new(&mut self.inner).poll_shutdown(cx)
+    }
+}
diff --git a/crates/wasi-http/src/lib.rs b/crates/wasi-http/src/lib.rs
index 66852af89..fd7600b9b 100644
--- a/crates/wasi-http/src/lib.rs
+++ b/crates/wasi-http/src/lib.rs
@@ -2,6 +2,7 @@ pub use crate::types::{WasiHttpCtx, WasiHttpView};
 
 pub mod body;
 pub mod http_impl;
+pub mod io;
 pub mod proxy;
 pub mod types;
 pub mod types_impl;
diff --git a/crates/wasi-http/src/types.rs b/crates/wasi-http/src/types.rs
index 4473b3912..1657d9a36 100644
--- a/crates/wasi-http/src/types.rs
+++ b/crates/wasi-http/src/types.rs
@@ -1,6 +1,7 @@
 //! Implements the base structure (i.e. [WasiHttpCtx]) that will provide the
 //! implementation of the wasi-http API.
 
+use crate::io::TokioIo;
 use crate::{
     bindings::http::types::{self, Method, Scheme},
     body::{HostIncomingBody, HyperIncomingBody, HyperOutgoingBody},
@@ -200,6 +201,7 @@ async fn handler(
                 tracing::warn!("tls protocol error: {e:?}");
                 types::ErrorCode::TlsProtocolError
             })?;
+            let stream = TokioIo::new(stream);
 
             let (sender, conn) = timeout(
                 connect_timeout,
@@ -221,6 +223,7 @@ async fn handler(
             (sender, worker)
         }
     } else {
+        let tcp_stream = TokioIo::new(tcp_stream);
         let (sender, conn) = timeout(
             connect_timeout,
             // TODO: we should plumb the builder through the http context, and use it here
@@ -253,6 +256,7 @@ async fn handler(
         between_bytes_timeout,
     })
 }
+
 impl From<http::Method> for types::Method {
     fn from(method: http::Method) -> Self {
         if method == http::Method::GET {
diff --git a/src/commands/serve.rs b/src/commands/serve.rs
index 2ce05a0e1..d3b8c9e19 100644
--- a/src/commands/serve.rs
+++ b/src/commands/serve.rs
@@ -14,6 +14,7 @@ use wasmtime::{Engine, Store, StoreLimits};
 use wasmtime_wasi::preview2::{
     self, StreamError, StreamResult, Table, WasiCtx, WasiCtxBuilder, WasiView,
 };
+use wasmtime_wasi_http::io::TokioIo;
 use wasmtime_wasi_http::{
     bindings::http::types as http_types, body::HyperOutgoingBody, hyper_response_error,
     WasiHttpCtx, WasiHttpView,
@@ -267,6 +268,7 @@ impl ServeCommand {
 
         loop {
             let (stream, _) = listener.accept().await?;
+            let stream = TokioIo::new(stream);
             let h = handler.clone();
             tokio::task::spawn(async move {
                 if let Err(e) = http1::Builder::new()
@@ -347,7 +349,7 @@ impl hyper::service::Service<Request> for ProxyHandler {
     type Error = anyhow::Error;
     type Future = Pin<Box<dyn std::future::Future<Output = Result<Self::Response>> + Send>>;
 
-    fn call(&mut self, req: Request) -> Self::Future {
+    fn call(&self, req: Request) -> Self::Future {
         use http_body_util::BodyExt;
 
         let ProxyHandler(inner) = self.clone();
diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml
index bed9b135b..b4d557e07 100644
--- a/supply-chain/audits.toml
+++ b/supply-chain/audits.toml
@@ -1325,6 +1325,12 @@ who = "Jamey Sharp <jsharp@fastly.com>"
 criteria = "safe-to-deploy"
 delta = "0.3.1 -> 0.3.0"
 
+[[audits.h2]]
+who = "Alex Crichton <alex@alexcrichton.com>"
+criteria = "safe-to-deploy"
+delta = "0.3.19 -> 0.4.0"
+notes = "A number of changes but nothing adding new `unsafe` or anything outside the purview of what this crate already manages."
+
 [[audits.hashbrown]]
 who = "Chris Fallin <chris@cfallin.org>"
 criteria = "safe-to-deploy"
@@ -1348,23 +1354,51 @@ who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
 delta = "0.2.0 -> 0.3.0"
 
+[[audits.http]]
+who = "Alex Crichton <alex@alexcrichton.com>"
+criteria = "safe-to-deploy"
+delta = "0.2.9 -> 1.0.0"
+notes = "Minor changes leading up to the 1.0.0 release and nothing fundamentally new here."
+
 [[audits.http-body]]
 who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
 version = "1.0.0-rc.2"
 
+[[audits.http-body]]
+who = "Alex Crichton <alex@alexcrichton.com>"
+criteria = "safe-to-deploy"
+delta = "1.0.0-rc.2 -> 1.0.0"
+notes = "Only minor changes made for a stable release."
+
 [[audits.http-body-util]]
 who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
 version = "0.1.0-rc.2"
 notes = "only one use of unsafe related to pin projection. unclear to me why pin_project! is used in many modules of the project, but the expanded output of that macro is inlined in either.rs"
 
+[[audits.http-body-util]]
+who = "Alex Crichton <alex@alexcrichton.com>"
+criteria = "safe-to-deploy"
+delta = "0.1.0-rc.2 -> 0.1.0"
+notes = "Minor documentation updates an additions, nothing major."
+
 [[audits.httpdate]]
 who = "Pat Hickey <phickey@fastly.com>"
 criteria = "safe-to-deploy"
 version = "1.0.2"
 notes = "No unsafety, no io"
 
+[[audits.hyper]]
+who = "Alex Crichton <alex@alexcrichton.com>"
+criteria = "safe-to-deploy"
+delta = "1.0.0-rc.3 -> 1.0.1"
+notes = """
+Quite a few changes here relative to the last RC but everything is related to
+refactorings and such. No new fundamental addition of functionality or
+substantially new unsafe code.
+"""
+
 [[audits.id-arena]]
 who = "Nick Fitzgerald <fitzgen@gmail.com>"
 criteria = "safe-to-deploy"


Test patch:
diff --git a/crates/wasi-http/tests/all/http_server.rs b/crates/wasi-http/tests/all/http_server.rs
index d22fe5b20..99482c0b1 100644
--- a/crates/wasi-http/tests/all/http_server.rs
+++ b/crates/wasi-http/tests/all/http_server.rs
@@ -7,6 +7,7 @@ use std::{
     thread::JoinHandle,
 };
 use tokio::net::TcpListener;
+use wasmtime_wasi_http::io::TokioIo;
 
 async fn test(
     mut req: Request<hyper::body::Incoming>,
@@ -30,7 +31,9 @@ pub struct Server {
 }
 
 impl Server {
-    fn new<F>(run: impl FnOnce(tokio::net::TcpStream) -> F + Send + Sync + 'static) -> Result<Self>
+    fn new<F>(
+        run: impl FnOnce(TokioIo<tokio::net::TcpStream>) -> F + Send + Sync + 'static,
+    ) -> Result<Self>
     where
         F: Future<Output = Result<()>>,
     {
@@ -52,7 +55,7 @@ impl Server {
             rt.block_on(async move {
                 tracing::debug!("preparing to accept connection");
                 let (stream, _) = listener.accept().await.map_err(anyhow::Error::from)?;
-                run(stream).await
+                run(TokioIo::new(stream)).await
             })
         });
         Ok(Self {
diff --git a/crates/wasi-http/tests/all/main.rs b/crates/wasi-http/tests/all/main.rs
index 0479161f8..002e28b79 100644
--- a/crates/wasi-http/tests/all/main.rs
+++ b/crates/wasi-http/tests/all/main.rs
@@ -17,6 +17,7 @@ use wasmtime_wasi::preview2::{
 use wasmtime_wasi_http::{
     bindings::http::types::ErrorCode,
     body::HyperIncomingBody,
+    io::TokioIo,
     types::{self, HostFutureIncomingResponse, IncomingResponseInternal, OutgoingRequest},
     WasiHttpCtx, WasiHttpView,
 };
@@ -287,6 +288,7 @@ async fn do_wasi_http_hash_all(override_send_request: bool) -> Result<()> {
         let server = async move {
             loop {
                 let (stream, _) = listener.accept().await?;
+                let stream = TokioIo::new(stream);
                 let handle = handle.clone();
                 task::spawn(async move {
                     if let Err(e) = http1::Builder::new()
@@ -385,6 +387,7 @@ async fn wasi_http_double_echo() -> Result<()> {
     let server = async move {
         loop {
             let (stream, _) = listener.accept().await?;
+            let stream = TokioIo::new(stream);
             task::spawn(async move {
                 if let Err(e) = http1::Builder::new()
                     .keep_alive(true)