use std::{ io, net::{Ipv4Addr, SocketAddr}, }; use actix_rt::net::TcpStream; use actix_server::TestServer; use actix_service::{fn_service, Service, ServiceFactory}; use futures_core::future::LocalBoxFuture; use actix_tls::connect::{new_connector_factory, Connect, Resolve, Resolver}; #[actix_rt::test] async fn custom_resolver() { /// Always resolves to localhost with the given port. struct LocalOnlyResolver; impl Resolve for LocalOnlyResolver { fn lookup<'a>( &'a self, _host: &'a str, port: u16, ) -> LocalBoxFuture<'a, Result, Box>> { Box::pin(async move { let local = format!("127.0.0.1:{}", port).parse().unwrap(); Ok(vec![local]) }) } } let addr = LocalOnlyResolver.lookup("example.com", 8080).await.unwrap()[0]; assert_eq!(addr, SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 8080)) } #[actix_rt::test] async fn custom_resolver_connect() { use trust_dns_resolver::TokioAsyncResolver; let srv = TestServer::with(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) })); struct MyResolver { trust_dns: TokioAsyncResolver, } impl Resolve for MyResolver { fn lookup<'a>( &'a self, host: &'a str, port: u16, ) -> LocalBoxFuture<'a, Result, Box>> { Box::pin(async move { let res = self .trust_dns .lookup_ip(host) .await? .iter() .map(|ip| SocketAddr::new(ip, port)) .collect(); Ok(res) }) } } let resolver = MyResolver { trust_dns: TokioAsyncResolver::tokio_from_system_conf().unwrap(), }; let resolver = Resolver::new_custom(resolver); let factory = new_connector_factory(resolver); let conn = factory.new_service(()).await.unwrap(); let con = conn .call(Connect::with_addr("example.com", srv.addr())) .await .unwrap(); assert_eq!(con.peer_addr().unwrap(), srv.addr()); }