Skip to content

Commit

Permalink
Merge branch 'main' into fix/rustls-crypto-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
algesten authored Jan 5, 2025
2 parents 28d3114 + a9ef156 commit 484078f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 53 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* `TlsConfig::unversioned_rustls_crypto_provider()` (#931)
* Feature `rustls-no-provider` to compile without ring (#931)
* Re-enable CONNECT proxy support (#932)
* Body::content_length (#927)
* Handle Authorization: Basic from URI (#923)
* Remove many uses of Box::new() from Connector chain (#919)
Expand Down
106 changes: 53 additions & 53 deletions src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ impl Proxy {
///
/// This operates on the previous chained transport typically a TcpConnector optionally
/// wrapped in TLS.
pub struct ConnectProxyConnector;
#[derive(Default)]
pub struct ConnectProxyConnector(());

impl<In: Transport> Connector<In> for ConnectProxyConnector {
type Out = In;
Expand All @@ -201,72 +202,71 @@ impl<In: Transport> Connector<In> for ConnectProxyConnector {
};

let is_connect_proxy = details.config.connect_proxy_uri().is_some();
if !is_connect_proxy {
return Ok(Some(transport));
}

if is_connect_proxy {
// unwrap is ok because connect_proxy_uri() above checks it.
let proxy = details.config.proxy().unwrap();

let mut w = TransportAdapter::new(transport);
// unwrap is ok because connect_proxy_uri() above checks it.
let proxy = details.config.proxy().unwrap();

let uri = &details.uri;
uri.ensure_valid_url()?;
let mut w = TransportAdapter::new(transport);

// All these unwrap() are ok because ensure_valid_uri() above checks them.
let host = uri.host().unwrap();
let port = uri
.port_u16()
.unwrap_or(uri.scheme().unwrap().default_port().unwrap());
let uri = &details.uri;
uri.ensure_valid_url()?;

write!(w, "CONNECT {}:{} HTTP/1.1\r\n", host, port)?;
write!(w, "Host: {}:{}\r\n", host, port)?;
if let Some(v) = details.config.user_agent().as_str(DEFAULT_USER_AGENT) {
write!(w, "User-Agent: {}\r\n", v)?;
}
write!(w, "Proxy-Connection: Keep-Alive\r\n")?;
// All these unwrap() are ok because ensure_valid_uri() above checks them.
let host = uri.host().unwrap();
let port = uri
.port_u16()
.unwrap_or(uri.scheme().unwrap().default_port().unwrap());

let use_creds = proxy.username().is_some() || proxy.password().is_some();
write!(w, "CONNECT {}:{} HTTP/1.1\r\n", host, port)?;
write!(w, "Host: {}:{}\r\n", proxy.host(), proxy.port())?;
if let Some(v) = details.config.user_agent().as_str(DEFAULT_USER_AGENT) {
write!(w, "User-Agent: {}\r\n", v)?;
}
write!(w, "Proxy-Connection: Keep-Alive\r\n")?;

if use_creds {
let user = proxy.username().unwrap_or_default();
let pass = proxy.password().unwrap_or_default();
let creds = BASE64_STANDARD.encode(format!("{}:{}", user, pass));
write!(w, "Proxy-Authorization: basic {}\r\n", creds)?;
}
let use_creds = proxy.username().is_some() || proxy.password().is_some();

write!(w, "\r\n")?;
w.flush()?;
if use_creds {
let user = proxy.username().unwrap_or_default();
let pass = proxy.password().unwrap_or_default();
let creds = BASE64_STANDARD.encode(format!("{}:{}", user, pass));
write!(w, "Proxy-Authorization: basic {}\r\n", creds)?;
}

let mut transport = w.into_inner();
write!(w, "\r\n")?;
w.flush()?;

let response = loop {
let made_progress = transport.await_input(details.timeout)?;
let buffers = transport.buffers();
let input = buffers.input();
let Some((used_input, response)) = try_parse_response::<20>(input)? else {
if !made_progress {
let reason = "proxy server did not respond".to_string();
return Err(Error::ConnectProxyFailed(reason));
}
continue;
};
buffers.input_consume(used_input);
break response;
};
let mut transport = w.into_inner();

match response.status() {
StatusCode::OK => {
trace!("CONNECT proxy connected");
}
x => {
let reason = format!("proxy server responded {}/{}", x.as_u16(), x.as_str());
let response = loop {
let made_progress = transport.await_input(details.timeout)?;
let buffers = transport.buffers();
let input = buffers.input();
let Some((used_input, response)) = try_parse_response::<20>(input)? else {
if !made_progress {
let reason = "proxy server did not respond".to_string();
return Err(Error::ConnectProxyFailed(reason));
}
}
continue;
};
buffers.input_consume(used_input);
break response;
};

Ok(Some(transport))
} else {
Ok(Some(transport))
match response.status() {
StatusCode::OK => {
trace!("CONNECT proxy connected");
}
x => {
let reason = format!("proxy server responded {}/{}", x.as_u16(), x.as_str());
return Err(Error::ConnectProxyFailed(reason));
}
}

Ok(Some(transport))
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/unversioned/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ impl Default for DefaultConnector {
crate::tls::TlsProvider::NativeTls,
));

let inner = inner.chain(ConnectProxyConnector::default());

DefaultConnector {
inner: boxed_connector(inner),
}
Expand Down

0 comments on commit 484078f

Please sign in to comment.