mirror of
https://github.com/openai/codex.git
synced 2026-09-10 20:26:47 +00:00
## What changed - Accept root `http://` and `https://` URLs in `--code-mode-host` and use the shared gRPC session provider for those endpoints. - Keep `ws://` and `wss://` URLs on the existing WebSocket transport. - Reject paths, queries, fragments, and credentials where unsupported, without exposing gRPC URL credentials in command-line validation errors. ## Testing - Cover argument parsing and transport selection for both remote protocols. - Exercise a gRPC host shared across app-server threads and verify credential rejection does not disclose usernames or passwords. GitOrigin-RevId: b6516a85cf76db5c4cea620f89ef866d8af30cf0
92 lines
2.9 KiB
Rust
92 lines
2.9 KiB
Rust
use std::ffi::OsStr;
|
|
|
|
use clap::Args;
|
|
use clap::builder::TypedValueParser;
|
|
use clap::error::ErrorKind;
|
|
use url::Url;
|
|
|
|
/// Selects the code-mode host for a single app-server process.
|
|
#[derive(Args, Debug, Clone, Default, PartialEq, Eq)]
|
|
pub struct AppServerCodeModeHostArgs {
|
|
/// Connect to a remote code-mode host instead of starting a local host.
|
|
#[arg(
|
|
long = "code-mode-host",
|
|
value_name = "URL",
|
|
value_parser = RedactedHostUrlParser
|
|
)]
|
|
pub code_mode_host: Option<Url>,
|
|
}
|
|
|
|
/// Process-scoped transport used to reach the code-mode host.
|
|
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
pub enum CodeModeHostTransport {
|
|
/// Start and own the default local code-mode host.
|
|
#[default]
|
|
Local,
|
|
/// Share a connection to the specified remote code-mode host.
|
|
WebSocket(Url),
|
|
/// Share an HTTP/2 gRPC connection to the specified remote code-mode host.
|
|
Grpc(Url),
|
|
}
|
|
|
|
impl From<AppServerCodeModeHostArgs> for CodeModeHostTransport {
|
|
fn from(args: AppServerCodeModeHostArgs) -> Self {
|
|
match args.code_mode_host {
|
|
Some(url) if matches!(url.scheme(), "http" | "https") => Self::Grpc(url),
|
|
Some(url) => Self::WebSocket(url),
|
|
None => Self::Local,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct RedactedHostUrlParser;
|
|
|
|
impl TypedValueParser for RedactedHostUrlParser {
|
|
type Value = Url;
|
|
|
|
fn parse_ref(
|
|
&self,
|
|
command: &clap::Command,
|
|
_argument: Option<&clap::Arg>,
|
|
value: &OsStr,
|
|
) -> Result<Self::Value, clap::Error> {
|
|
let value = value.to_str().ok_or_else(|| {
|
|
clap::Error::raw(
|
|
ErrorKind::InvalidUtf8,
|
|
"code-mode host URL must contain valid UTF-8",
|
|
)
|
|
.with_cmd(command)
|
|
})?;
|
|
|
|
parse_host_url(value)
|
|
.map_err(|error| clap::Error::raw(ErrorKind::ValueValidation, error).with_cmd(command))
|
|
}
|
|
}
|
|
|
|
fn parse_host_url(value: &str) -> Result<Url, String> {
|
|
let url = Url::parse(value).map_err(|error| format!("invalid code-mode host URL: {error}"))?;
|
|
if !matches!(url.scheme(), "ws" | "wss" | "http" | "https") || url.host_str().is_none() {
|
|
return Err(
|
|
"code-mode host URL must use ws://, wss://, http://, or https:// with a host"
|
|
.to_string(),
|
|
);
|
|
}
|
|
if url.fragment().is_some() {
|
|
return Err("code-mode host URL must not contain a fragment".to_string());
|
|
}
|
|
if matches!(url.scheme(), "http" | "https") {
|
|
if !url.username().is_empty() || url.password().is_some() {
|
|
return Err("gRPC code-mode host URL must not contain credentials".to_string());
|
|
}
|
|
if url.path() != "/" || url.query().is_some() {
|
|
return Err("gRPC code-mode host URL must not contain a path or query".to_string());
|
|
}
|
|
}
|
|
Ok(url)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "code_mode_host_tests.rs"]
|
|
mod tests;
|