diff --git a/Cargo.lock b/Cargo.lock index 4ec92eb..91aa10e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,7 +204,8 @@ dependencies = [ "async-trait", "fs-err", "glob", - "hyper 0.14.28", + "hyper 1.1.0", + "hyper-util", "prost", "prost-build", "prost-wkt", diff --git a/crates/twirp/Cargo.toml b/crates/twirp/Cargo.toml index de700ba..42d71d1 100644 --- a/crates/twirp/Cargo.toml +++ b/crates/twirp/Cargo.toml @@ -31,3 +31,6 @@ pin-project = "1.1" # For the test-support feature async-trait = { version = "0.1", optional = true } tokio = { version = "1.33", features = [], optional = true } + +[dev-dependencies] +tokio = { version = "1.33", features = ["rt", "macros"] } diff --git a/crates/twirp/src/test.rs b/crates/twirp/src/test.rs index 9571964..a5d3809 100644 --- a/crates/twirp/src/test.rs +++ b/crates/twirp/src/test.rs @@ -7,52 +7,54 @@ use async_trait::async_trait; use http_body_util::BodyExt; use hyper::body::Incoming; use hyper::server::conn::http1; -use hyper::service::service_fn; -use hyper::Request; +use hyper::service::{service_fn, Service}; +use hyper::{Request, Response}; use hyper_util::rt::TokioIo; use serde::de::DeserializeOwned; -use tokio::net::{TcpListener, TcpStream}; +use tokio::net::TcpListener; use tokio::task::JoinHandle; -use crate::{error, Body, Client, Result, Router, TwirpErrorResponse}; +use crate::{error, Body, Client, GenericError, Result, Router, TwirpErrorResponse}; -async fn test_server_handle_connection(io: TokioIo, router: Arc) { - let service = service_fn(move |req: Request| { - let router = Arc::clone(&router); - async move { - let req = req.map(|body| Body::new(body)); - crate::serve(router.clone(), req).await - } - }); - if let Err(err) = http1::Builder::new().serve_connection(io, service).await { - eprintln!("Error serving connection: {err:?}"); - } -} - -async fn test_server_main( - tcp_listener: TcpListener, - router: Arc, -) -> Result<(), std::io::Error> { +async fn test_server_main(tcp_listener: TcpListener, service: S) -> Result<(), std::io::Error> +where + S: Clone + Service, Response = Response> + Send + 'static, + S::Future: Send + 'static, + S::Error: Into, +{ loop { let (stream, _) = tcp_listener.accept().await?; let io = TokioIo::new(stream); - let router = Arc::clone(&router); - tokio::spawn(test_server_handle_connection(io, router)); + let service = service.clone(); + let task = async move { + if let Err(err) = http1::Builder::new().serve_connection(io, service).await { + eprintln!("test server: error serving connection: {err:#}"); + } + }; + tokio::spawn(task); } } pub async fn run_test_server(port: u16) -> JoinHandle> { - let router = test_api_router().await; + let router = test_api_router(); + let service = service_fn(move |req: Request| { + let router = Arc::clone(&router); + async move { + let req = req.map(Body::new); + crate::serve(router, req).await + } + }); + let addr: SocketAddr = ([127, 0, 0, 1], port).into(); let tcp_listener = TcpListener::bind(&addr).await.unwrap(); - let server = test_server_main(tcp_listener, router); + let server = test_server_main(tcp_listener, service); println!("Listening on {addr}"); let h = tokio::spawn(server); tokio::time::sleep(Duration::from_millis(100)).await; h } -pub async fn test_api_router() -> Arc { +pub fn test_api_router() -> Arc { let api = Arc::new(TestAPIServer {}); let mut router = Router::default(); // NB: This would be generated