diff --git a/Cargo.toml b/Cargo.toml index 6f38c17f..deda2b50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "yup-hyper-mock" -version = "6.0.0" +version = "8.0.0" authors = ["Sean McArthur ", "Jonathan Reem ", "Sebastian Thiel ", @@ -10,15 +10,17 @@ repository = "https://github.com/Byron/yup-hyper-mock" documentation = "http://byron.github.io/yup-hyper-mock" license = "MIT" include = ["src/**/*", "Cargo.toml"] -edition = "2018" +edition = "2021" [dependencies] -hyper = { version = "0.14", features = ["client", "http1", "runtime", "stream"] } +http-body-util = "0.1.0" +hyper = { version = "1.1", features = ["client", "http1"] } +hyper-util = { version = "0.1.2", features = ["tokio", "http1", "client-legacy"] } log = ">= 0.4" futures = "0.3" -tokio = { version = "1.0", features = ["io-util"] } -mio = "0.8" +tokio = { version = "1.35", features = ["io-util"] } +tower-service = "0.3" [dev-dependencies] -env_logger = "0.7" +env_logger = "0.10" tokio = { version = "1.0", features = ["rt", "macros"] } diff --git a/README.md b/README.md index 2ea923da..c856b9a3 100644 --- a/README.md +++ b/README.md @@ -12,19 +12,14 @@ yup-hyper-mock = "*" log = "*" # log macros are used within yup-hyper-mock ``` -Link it in case you are testing only in your `src/(lib.rs|main.rs)` -```Rust -#[cfg(test)] #[macro_use] -extern crate yup_hyper_mock as hyper_mock -``` - In your tests module ```Rust #[cfg(test)] mod tests { use hyper; + use hyper_util::client::legacy::Client; - mock_connector!(MockRedirectPolicy { + yup_hyper_mock::mock_connector!(MockRedirectPolicy { "http://127.0.0.1" => "HTTP/1.1 301 Redirect\r\n\ Location: http://127.0.0.2\r\n\ Server: mock1\r\n\ @@ -41,13 +36,21 @@ mod tests { " }); - #[test] - fn test_redirect_followall() { - let mut client = hyper::Client::with_connector(MockRedirectPolicy::default()); - client.set_redirect_policy(hyper::client::RedirectPolicy::FollowAll); + #[tokio::test] + async fn test_redirect_followall() { + let builder = + hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()); + let client: Client> = + builder.build(MockRedirectPolicy::default()); + + let res = client + .get(hyper::Uri::from_static("http://127.0.0.1")) + .await + .unwrap(); - let res = client.get("http://127.0.0.1").send().unwrap(); - assert_eq!(res.headers.get(), Some(&hyper::header::Server("mock3".to_owned()))); + let headers = res.headers(); + assert!(headers.contains_key("Server")); + assert_eq!(headers["Server"], "mock1"); } } ``` diff --git a/src/lib.rs b/src/lib.rs index 880aa671..2cc5808e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,8 +26,7 @@ //! extern crate "yup-hyper-mock" as hyper_mock //! ``` -#[macro_use] -extern crate log; +use log::debug; use std::collections::HashMap; use std::pin::Pin; @@ -37,7 +36,8 @@ use std::task::{Context, Poll}; use futures; use futures::lock::Mutex; use futures::Future; -use hyper::{service::Service, Uri}; +use hyper::Uri; +use tower_service::Service; mod streams; pub use crate::streams::MockPollStream; @@ -60,7 +60,7 @@ macro_rules! mock_connector ( } } - impl hyper::service::Service for $name { + impl tower_service::Service for $name { type Response = $crate::MockPollStream; type Error = std::io::Error; type Future = std::pin::Pin> + Send>>; @@ -127,7 +127,7 @@ macro_rules! mock_connector_in_order ( } } - impl hyper::service::Service for $name { + impl tower_service::Service for $name { type Response = $crate::MockPollStream; type Error = std::io::Error; type Future = std::pin::Pin> + Send>>; diff --git a/src/streams.rs b/src/streams.rs index ed6f0280..fdd2adf5 100644 --- a/src/streams.rs +++ b/src/streams.rs @@ -6,8 +6,9 @@ use std::{ task::{Context, Poll, Waker}, }; -use hyper::client::connect::{Connected, Connection}; -use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; +use hyper::rt::ReadBufCursor; +use hyper_util::client::legacy::connect::{Connected, Connection}; +use log::trace; pub struct MockPollStream { data: Vec, @@ -27,27 +28,29 @@ impl MockPollStream { } } -impl AsyncRead for MockPollStream { +impl hyper::rt::Read for MockPollStream { fn poll_read( mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut ReadBuf, + cx: &mut Context<'_>, + mut buf: ReadBufCursor<'_>, ) -> Poll> { if !self.ready_for_response { trace!("Not ready for read yet"); self.waker = Some(cx.waker().clone()); return Poll::Pending; } + let mut read_buf = unsafe { tokio::io::ReadBuf::uninit(buf.as_mut()) }; trace!( "Buffer size: {}, Data size: {}, Pos: {}", - buf.remaining(), + read_buf.remaining(), self.data.len(), self.pos ); - let n = min(buf.remaining(), self.data.len() - self.pos); + let n = min(read_buf.remaining(), self.data.len() - self.pos); let read_until = self.pos + n; - buf.put_slice(&self.data[self.pos..read_until]); + read_buf.put_slice(&self.data[self.pos..read_until]); self.pos = read_until; + unsafe { buf.advance(n) }; trace!( "Read {} bytes: '{}'", n, @@ -58,8 +61,12 @@ impl AsyncRead for MockPollStream { } } -impl AsyncWrite for MockPollStream { - fn poll_write(self: Pin<&mut Self>, _cx: &mut Context, data: &[u8]) -> Poll> { +impl hyper::rt::Write for MockPollStream { + fn poll_write( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + data: &[u8], + ) -> Poll> { trace!( "Request data: {}", str::from_utf8(data).unwrap_or("") @@ -74,11 +81,11 @@ impl AsyncWrite for MockPollStream { Poll::Ready(Ok(data.len())) } - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context) -> Poll> { + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } - fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context) -> Poll> { + fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } } diff --git a/tests/connector.rs b/tests/connector.rs index e4ec5c94..0cbb8522 100644 --- a/tests/connector.rs +++ b/tests/connector.rs @@ -1,23 +1,19 @@ //! Test usage of connectors which work entirely without macros -use env_logger; +use std::io; -use futures::stream::TryStreamExt; - -use hyper::{client::Client, header, Body, Response}; +use http_body_util::{combinators::BoxBody, BodyExt}; +use hyper::{ + body::{Bytes, Incoming}, + header, Response, +}; +use hyper_util::{client::legacy::Client, rt::TokioExecutor}; use yup_hyper_mock::{HostToReplyConnector, SequentialConnector}; -async fn result_to_bytes(res: Response) -> String { - let buf = res - .into_body() - .try_fold(Vec::new(), |mut buf, bytes| { - buf.extend_from_slice(bytes.as_ref()); - async move { Ok(buf) } - }) - .await - .unwrap(); - String::from_utf8(buf).unwrap() +async fn result_to_bytes(res: Response) -> String { + let buf = res.into_body().collect().await.unwrap().to_bytes(); + String::from_utf8(buf.to_vec()).unwrap() } #[tokio::test] @@ -36,7 +32,8 @@ async fn test_sequential_mock() { .to_string(), ]); - let client = Client::builder().build::(c); + let client = Client::builder(TokioExecutor::new()) + .build::>(c); let res = client .get("http://127.0.0.1".parse().unwrap()) @@ -83,9 +80,13 @@ async fn test_redirect_followall() { .to_string(), ); - let client = Client::builder().build(c); + let client = Client::builder(TokioExecutor::new()).build(c); - async fn check_server(client: &Client, url: &str, server: &str) { + async fn check_server( + client: &Client>, + url: &str, + server: &str, + ) { let res = client.get(url.parse().unwrap()).await.unwrap(); let header = header::HeaderValue::from_str(&server).unwrap(); assert_eq!(res.headers().get(header::SERVER), Some(&header)); diff --git a/tests/macros.rs b/tests/macros.rs index 1215af63..d5b2af3a 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -1,10 +1,15 @@ -use hyper; -#[macro_use] -extern crate yup_hyper_mock; +use std::io; -use futures::stream::TryStreamExt; +use http_body_util::{combinators::BoxBody, BodyExt}; +use hyper::{ + self, + body::{Bytes, Incoming}, +}; -use hyper::{client::Client, header, Body, Response}; +use yup_hyper_mock::{mock_connector, mock_connector_in_order}; + +use hyper::{header, Response}; +use hyper_util::{client::legacy::Client, rt::TokioExecutor}; mock_connector_in_order! (MockSequential { "HTTP/1.1 200 OK\r\n\ @@ -35,24 +40,21 @@ mock_connector!(MockRedirectPolicy { " }); -async fn result_to_bytes(res: Response) -> String { - let buf = res - .into_body() - .try_fold(Vec::new(), |mut buf, bytes| { - buf.extend_from_slice(bytes.as_ref()); - async move { Ok(buf) } - }) - .await - .unwrap(); - String::from_utf8(buf).unwrap() +async fn result_to_bytes(res: Response) -> String { + let buf = res.into_body().collect().await.unwrap().to_bytes(); + String::from_utf8(buf.to_vec()).unwrap() } /// Just to test the result of `mock_connector!` - this test was copied from hyper. #[tokio::test] async fn test_redirect_followall() { - let client = Client::builder().build::(MockRedirectPolicy::default()); + let client = Client::builder(TokioExecutor::new()).build(MockRedirectPolicy::default()); - async fn check_server(client: &Client, url: &str, server: &str) { + async fn check_server( + client: &Client>, + url: &str, + server: &str, + ) { let res = client.get(url.parse().unwrap()).await.unwrap(); let header = header::HeaderValue::from_str(&server).unwrap(); assert_eq!(res.headers().get(header::SERVER), Some(&header)); @@ -65,7 +67,8 @@ async fn test_redirect_followall() { #[tokio::test] async fn test_sequential_mock() { - let client = Client::builder().build::(MockSequential::default()); + let client = Client::builder(TokioExecutor::new()) + .build::>(MockSequential::default()); let res = client .get("http://127.0.0.1".parse().unwrap())