diff --git a/src/proxy.rs b/src/proxy.rs index df1baba9..8b509248 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -9,6 +9,7 @@ use crate::{ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum Proto { HTTP, + HTTPS, SOCKS4, SOCKS4A, SOCKS5, @@ -119,6 +120,7 @@ impl Proxy { let proto = if proxy_parts.len() == 2 { match proxy_parts.next() { Some("http") => Proto::HTTP, + Some("https") => Proto::HTTPS, Some("socks4") => Proto::SOCKS4, Some("socks4a") => Proto::SOCKS4A, Some("socks") => Proto::SOCKS5, @@ -153,7 +155,10 @@ impl Proxy { server, user, password, - port: port.unwrap_or(8080), + port: port.unwrap_or(match proto { + Proto::HTTPS => 443, + _ => 8080, + }), proto, }) } @@ -228,6 +233,13 @@ mod tests { assert_eq!(proxy.proto, Proto::HTTP); } + #[test] + fn parse_proxy_https_server() { + let proxy = Proxy::new("https://localhost").unwrap(); + assert_eq!(proxy.server, String::from("localhost")); + assert_eq!(proxy.proto, Proto::HTTPS); + } + #[cfg(feature = "socks-proxy")] #[test] fn parse_proxy_socks4_user_pass_server_port() { diff --git a/src/stream.rs b/src/stream.rs index 8e7a36ee..e90aa94e 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -336,7 +336,7 @@ pub(crate) fn connect_https(unit: &Unit, hostname: &str) -> Result Result<(TcpStream, SocketAddr), Error> { +) -> Result<(Box, SocketAddr), Error> { let connect_deadline: Option = if let Some(timeout_connect) = unit.agent.config.timeout_connect { Instant::now().checked_add(timeout_connect) @@ -395,7 +395,8 @@ pub(crate) fn connect_host( // connect with a configured timeout. #[allow(clippy::unnecessary_unwrap)] - let stream = if proto.is_some() && Some(Proto::HTTP) != proto { + let stream = if proto.is_some() && Some(Proto::HTTP) != proto && Some(Proto::HTTPS) != proto + { connect_socks( unit, proxy.clone().unwrap(), @@ -419,7 +420,7 @@ pub(crate) fn connect_host( } } - let (mut stream, remote_addr) = if let Some(stream_and_addr) = any_stream_and_addr { + let (stream, remote_addr) = if let Some(stream_and_addr) = any_stream_and_addr { stream_and_addr } else if let Some(e) = any_err { return Err(ErrorKind::ConnectionFailed.msg("Connect error").src(e)); @@ -441,26 +442,38 @@ pub(crate) fn connect_host( stream.set_write_timeout(unit.agent.config.timeout_write)?; } - if proto == Some(Proto::HTTP) && unit.url.scheme() == "https" { + if (proto == Some(Proto::HTTP) || proto == Some(Proto::HTTPS)) && unit.url.scheme() == "https" { if let Some(ref proxy) = proxy { + let stream = stream.try_clone()?; + let mut s; + if proto == Some(Proto::HTTPS) { + s = unit + .agent + .config + .tls_config + .connect(&proxy.server, Box::new(stream))?; + } else { + s = Box::new(stream); + } write!( - stream, + s, "{}", proxy.connect(hostname, port, &unit.agent.config.user_agent) ) .unwrap(); - stream.flush()?; + s.flush()?; - let s = stream.try_clone()?; + // let s = s.try_clone()?; FIXME enable something like this so that we can return the stream let pool_key = PoolKey::from_parts(unit.url.scheme(), hostname, port); let pool_returner = PoolReturner::new(&unit.agent, pool_key); let s = Stream::new(s, remote_addr, pool_returner); let response = Response::do_from_stream(s, unit.clone())?; Proxy::verify_response(&response)?; + // TODO! return Ok((Box::new(s), remote_addr)) otherwise this tunnel is not used } } - Ok((stream, remote_addr)) + Ok((Box::new(stream), remote_addr)) } #[cfg(feature = "socks-proxy")]