use crate::examples::example_tests::utils::ExampleRunner;
use super::utils;
use rama::{
Layer,
http::{
BodyExtractExt, layer::error_handling::ErrorHandlerLayer, server::HttpServer,
service::web::Router,
},
layer::ArcLayer,
net::{
Protocol,
address::{ProxyAddress, SocketAddress},
user::{Basic, ProxyCredential},
},
rt::Executor,
tcp::server::TcpListener,
telemetry::tracing,
utils::str::non_empty_str,
};
#[tokio::test]
#[ignore]
async fn test_socks5_and_http_proxy() {
utils::init_tracing();
let runner = utils::ExampleRunner::interactive("socks5_and_http_proxy", None);
let http_socket_addr = spawn_http_server().await;
let uri = format!("http://{http_socket_addr}/ping");
let result = runner
.get(uri)
.extension(ProxyAddress::try_from("http://tom:clancy@127.0.0.1:62023").unwrap())
.send()
.await
.unwrap()
.try_into_string()
.await
.unwrap();
assert_eq!("pong", result);
tracing::info!("http ping-pong succeeded, bye now!");
test_http_client_over_socks5_proxy_connect(http_socket_addr, runner).await;
}
async fn test_http_client_over_socks5_proxy_connect(
http_socket_addr: SocketAddress,
runner: ExampleRunner,
) {
let proxy_socket_addr = SocketAddress::local_ipv4(62023);
tracing::info!(
"local servers up and running (proxy = {} ; http = {})",
proxy_socket_addr,
http_socket_addr,
);
let proxy_address = ProxyAddress {
protocol: Some(Protocol::SOCKS5),
address: proxy_socket_addr.into(),
credential: Some(ProxyCredential::Basic(Basic::new(
non_empty_str!("john"),
non_empty_str!("secret"),
))),
};
let uri = format!("http://{http_socket_addr}/ping");
tracing::info!(
url.full = %uri,
"try to make GET http request and try to receive response text",
);
let resp = runner
.get(uri)
.extension(proxy_address)
.send()
.await
.expect("make http request via socks5 proxy")
.try_into_string()
.await
.expect("get response text");
assert_eq!("pong", resp);
tracing::info!("socks5 ping-pong succeeded, bye now!")
}
async fn spawn_http_server() -> SocketAddress {
let tcp_service =
TcpListener::bind_address(SocketAddress::default_ipv4(63007), Executor::default())
.await
.expect("bind HTTP server on open port");
let bind_addr = tcp_service
.local_addr()
.expect("get bind address of http server")
.into();
let app = Router::new().with_get("/ping", "pong");
let server = HttpServer::auto(Executor::default())
.service((ArcLayer::new(), ErrorHandlerLayer::new()).into_layer(app));
tokio::spawn(tcp_service.serve(server));
bind_addr
}