mirror of
https://github.com/openai/codex.git
synced 2026-04-28 02:11:08 +03:00
feat: retain NetworkProxy, when appropriate (#11207)
As of this PR, `SessionServices` retains a `Option<StartedNetworkProxy>`, if appropriate. Now the `network` field on `Config` is `Option<NetworkProxySpec>` instead of `Option<NetworkProxy>`. Over in `Session::new()`, we invoke `NetworkProxySpec::start_proxy()` to create the `StartedNetworkProxy`, which is a new struct that retains the `NetworkProxy` as well as the `NetworkProxyHandle`. (Note that `Drop` is implemented for `NetworkProxyHandle` to ensure the proxies are shutdown when it is dropped.) The `NetworkProxy` from the `StartedNetworkProxy` is threaded through to the appropriate places. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/11207). * #11285 * __->__ #11207
This commit is contained in:
@@ -8,13 +8,13 @@ use std::net::SocketAddr;
|
||||
use tracing::warn;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
|
||||
pub struct NetworkProxyConfig {
|
||||
#[serde(default)]
|
||||
pub network: NetworkProxySettings,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct NetworkProxySettings {
|
||||
#[serde(default)]
|
||||
pub enabled: bool,
|
||||
@@ -205,6 +205,30 @@ fn resolve_addr(url: &str, default_port: u16) -> Result<SocketAddr> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn host_and_port_from_network_addr(value: &str, default_port: u16) -> String {
|
||||
let trimmed = value.trim();
|
||||
if trimmed.is_empty() {
|
||||
return "<missing>".to_string();
|
||||
}
|
||||
|
||||
let parts = match parse_host_port(trimmed, default_port) {
|
||||
Ok(parts) => parts,
|
||||
Err(_) => {
|
||||
return format_host_and_port(trimmed, default_port);
|
||||
}
|
||||
};
|
||||
|
||||
format_host_and_port(&parts.host, parts.port)
|
||||
}
|
||||
|
||||
fn format_host_and_port(host: &str, port: u16) -> String {
|
||||
if host.contains(':') {
|
||||
format!("[{host}]:{port}")
|
||||
} else {
|
||||
format!("{host}:{port}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct SocketAddressParts {
|
||||
host: String,
|
||||
@@ -280,14 +304,13 @@ fn parse_host_port_fallback(input: &str, default_port: u16) -> Result<SocketAddr
|
||||
// accidentally interpreting unbracketed IPv6 addresses as `host:port`.
|
||||
if host_port.bytes().filter(|b| *b == b':').count() == 1
|
||||
&& let Some((host, port)) = host_port.rsplit_once(':')
|
||||
&& let Ok(port) = port.parse::<u16>()
|
||||
{
|
||||
if host.is_empty() {
|
||||
bail!("missing host in network proxy address: {input}");
|
||||
}
|
||||
return Ok(SocketAddressParts {
|
||||
host: host.to_string(),
|
||||
port,
|
||||
port: port.parse::<u16>().ok().unwrap_or(default_port),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -376,12 +399,25 @@ mod tests {
|
||||
assert_eq!(
|
||||
parse_host_port("example.com:notaport", 3128).unwrap(),
|
||||
SocketAddressParts {
|
||||
host: "example.com:notaport".to_string(),
|
||||
host: "example.com".to_string(),
|
||||
port: 3128,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_and_port_from_network_addr_defaults_for_empty_string() {
|
||||
assert_eq!(host_and_port_from_network_addr("", 1234), "<missing>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_and_port_from_network_addr_formats_ipv6() {
|
||||
assert_eq!(
|
||||
host_and_port_from_network_addr("http://[::1]:8080", 3128),
|
||||
"[::1]:8080"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_addr_maps_localhost_to_loopback() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -15,6 +15,7 @@ mod upstream;
|
||||
|
||||
pub use config::NetworkMode;
|
||||
pub use config::NetworkProxyConfig;
|
||||
pub use config::host_and_port_from_network_addr;
|
||||
pub use network_policy::NetworkDecision;
|
||||
pub use network_policy::NetworkPolicyDecider;
|
||||
pub use network_policy::NetworkPolicyRequest;
|
||||
|
||||
@@ -363,6 +363,18 @@ impl NetworkProxy {
|
||||
NetworkProxyBuilder::default()
|
||||
}
|
||||
|
||||
pub fn http_addr(&self) -> SocketAddr {
|
||||
self.http_addr
|
||||
}
|
||||
|
||||
pub fn socks_addr(&self) -> SocketAddr {
|
||||
self.socks_addr
|
||||
}
|
||||
|
||||
pub fn admin_addr(&self) -> SocketAddr {
|
||||
self.admin_addr
|
||||
}
|
||||
|
||||
pub fn apply_to_env(&self, env: &mut HashMap<String, String>) {
|
||||
// Enforce proxying for child processes. We intentionally override existing values so
|
||||
// command-level environment cannot bypass the managed proxy endpoint.
|
||||
|
||||
Reference in New Issue
Block a user