#![cfg(target_arch = "x86_64")]
use hyper_tls::HttpsConnector;
use injectorpp::interface::injector::*;
use std::io::{BufRead, BufReader};
use std::net::TcpListener;
use std::thread;
use std::{io::Write, net::TcpStream as StdTcpStream};
use tokio::net::{TcpSocket, TcpStream};
use http_body_util::BodyExt;
use hyper::{Request, Uri};
use hyper_util::client::legacy::connect::HttpConnector;
use hyper_util::client::legacy::Client;
fn make_tcp_with_http_response() -> std::io::Result<TcpStream> {
let listener = TcpListener::bind(("127.0.0.1", 0))?;
let addr = listener.local_addr()?;
thread::spawn(move || {
if let Ok((mut sock, _)) = listener.accept() {
let mut reader = BufReader::new(&mut sock);
let mut request_line = String::new();
if reader.read_line(&mut request_line).is_ok() {
let mut line = String::new();
while reader.read_line(&mut line).is_ok() && line.trim() != "" {
line.clear();
}
}
let body =
r#"{"status": "ok", "message": "mock response", "headers": {"User-Agent": "hyper-test/1.0"}}"#;
let response = format!(
"HTTP/1.1 200 OK\r\n\
Content-Type: application/json\r\n\
Content-Length: {}\r\n\
Connection: close\r\n\
\r\n\
{}",
body.len(),
body
);
let _ = sock.write_all(response.as_bytes());
let _ = sock.flush();
let _ = sock.shutdown(std::net::Shutdown::Write);
}
});
let std_stream = StdTcpStream::connect(addr)?;
std_stream.set_nonblocking(true)?;
TcpStream::from_std(std_stream)
}
#[tokio::test]
async fn test_hyper_http_request() {
let mut injector = InjectorPP::new();
let temp_socket = TcpSocket::new_v4().expect("Failed to create temp socket");
let temp_addr = "127.0.0.1:80".parse().unwrap();
injector
.when_called_async(injectorpp::async_func!(
temp_socket.connect(temp_addr),
std::io::Result<TcpStream>
))
.will_return_async(injectorpp::async_return! {
make_tcp_with_http_response(),
std::io::Result<TcpStream>
});
let client = Client::builder(hyper_util::rt::TokioExecutor::new()).build(HttpConnector::new());
let request = Request::builder()
.method("GET")
.uri("http://127.0.0.1")
.header("User-Agent", "hyper-test/1.0")
.body(String::new())
.expect("Failed to build request");
let response = client
.request(request)
.await
.expect("Failed to send request");
assert!(
response.status().is_success(),
"Expected successful response"
);
assert_eq!(response.status().as_u16(), 200, "Expected status code 200");
let body_bytes = response
.into_body()
.collect()
.await
.expect("Failed to read response body")
.to_bytes();
let body_str =
String::from_utf8(body_bytes.to_vec()).expect("Failed to convert response body to string");
assert!(
body_str.contains("\"status\""),
"Response should contain status field"
);
assert!(
body_str.contains("mock response"),
"Response should contain mock message"
);
assert!(
body_str.contains("\"headers\""),
"Response should contain headers field"
);
assert!(
body_str.contains("hyper-test/1.0"),
"Response should contain our User-Agent"
);
}
#[tokio::test]
async fn test_hyper_https_request() {
let mut injector = InjectorPP::new();
let temp_socket = TcpSocket::new_v4().expect("Failed to create temp socket");
let temp_addr = "127.0.0.1:80".parse().unwrap();
injector
.when_called_async(injectorpp::async_func!(
temp_socket.connect(temp_addr),
std::io::Result<TcpStream>
))
.will_return_async(injectorpp::async_return! {
make_tcp_with_http_response(),
std::io::Result<TcpStream>
});
injector
.when_called(injectorpp::func!(fn (Uri::scheme_str)(&Uri) -> Option<&str>))
.will_execute(injectorpp::fake!(
func_type: fn(_uri: &Uri) -> Option<&str>,
returns: Some("http")
));
let client = Client::builder(hyper_util::rt::TokioExecutor::new()).build(HttpsConnector::new());
let request = Request::builder()
.method("GET")
.uri("https://127.0.0.1")
.header("User-Agent", "hyper-test/1.0")
.body(String::new())
.expect("Failed to build request");
let response = client
.request(request)
.await
.expect("Failed to send request");
assert!(
response.status().is_success(),
"Expected successful response"
);
assert_eq!(response.status().as_u16(), 200, "Expected status code 200");
let body_bytes = response
.into_body()
.collect()
.await
.expect("Failed to read response body")
.to_bytes();
let body_str =
String::from_utf8(body_bytes.to_vec()).expect("Failed to convert response body to string");
assert!(
body_str.contains("\"status\""),
"Response should contain status field"
);
assert!(
body_str.contains("mock response"),
"Response should contain mock message"
);
assert!(
body_str.contains("\"headers\""),
"Response should contain headers field"
);
assert!(
body_str.contains("hyper-test/1.0"),
"Response should contain our User-Agent"
);
}