Files
codex/prs/bolinfest/study/PR-2437-study.md
2025-09-02 15:17:45 -07:00

4.2 KiB
Raw Blame History

DOs

  • Sanitize Header Tokens: Clean any env-derived token before adding it to headers.
fn is_valid_header_value_char(c: char) -> bool {
    c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.' | '/')
}

fn sanitize_header_value(value: &str) -> String {
    value.chars().map(|c| if is_valid_header_value_char(c) { c } else { '_' }).collect()
}

// Usage
let token = sanitize_header_value(&format!("WezTerm/{v}"));
  • Use Concise Return-if/else: Prefer a single expression to avoid duplicate returns.
return if !v.trim().is_empty() {
    format!("WezTerm/{v}")
} else {
    "WezTerm".to_string()
};
  • Validate Env Vars: Check presence and non-emptiness before use.
if let Ok(tp) = std::env::var("TERM_PROGRAM") && !tp.trim().is_empty() {
    let ver = std::env::var("TERM_PROGRAM_VERSION").ok();
    return match ver {
        Some(v) if !v.trim().is_empty() => format!("{tp}/{v}"),
        _ => tp,
    };
}
  • Cache Detection Once: Compute terminal UA once with OnceLock.
use std::sync::OnceLock;

static TERMINAL: OnceLock<String> = OnceLock::new();

pub fn user_agent() -> String {
    TERMINAL.get_or_init(detect_terminal).to_string()
}
  • Append Terminal to UA String: Extend the UA format and keep variables inline.
pub fn get_codex_user_agent(originator: Option<&str>) -> String {
    let build_version = env!("CARGO_PKG_VERSION");
    let os_info = os_info::get();
    format!(
        "{}/{build_version} ({} {}; {}) {}",
        originator.unwrap_or("codex_cli_rs"),
        os_info.os_type(),
        os_info.version(),
        os_info.architecture().unwrap_or("unknown"),
        crate::terminal::user_agent()
    )
}
  • Update Tests for New Shape: Adjust regex to include the terminal token.
use regex_lite::Regex;

let re = Regex::new(
    r"^codex_cli_rs/\d+\.\d+\.\d+ \(Mac OS \d+\.\d+\.\d+; (x86_64|arm64)\) (\S+)$"
).unwrap();
assert!(re.is_match(&get_codex_user_agent(None)));
  • Provide Clear Fallbacks: Detect common terminals; fall back to TERM or unknown.
fn detect_terminal() -> String {
    // … TERM_PROGRAM branch …
    if let Ok(v) = std::env::var("WEZTERM_VERSION") {
        return if !v.trim().is_empty() { format!("WezTerm/{v}") } else { "WezTerm".to_string() };
    } else if std::env::var("KITTY_WINDOW_ID").is_ok()
        || std::env::var("TERM").map(|t| t.contains("kitty")).unwrap_or(false) {
        return "kitty".to_string();
    } else if std::env::var("ALACRITTY_SOCKET").is_ok()
        || std::env::var("TERM").map(|t| t == "alacritty").unwrap_or(false) {
        return "Alacritty".to_string();
    } else if let Ok(v) = std::env::var("KONSOLE_VERSION") {
        return if !v.trim().is_empty() { format!("Konsole/{v}") } else { "Konsole".to_string() };
    } else if std::env::var("GNOME_TERMINAL_SCREEN").is_ok() {
        return "gnome-terminal".to_string();
    } else if let Ok(v) = std::env::var("VTE_VERSION") {
        return if !v.trim().is_empty() { format!("VTE/{v}") } else { "VTE".to_string() };
    } else if std::env::var("WT_SESSION").is_ok() {
        return "WindowsTerminal".to_string();
    }
    std::env::var("TERM").unwrap_or_else(|_| "unknown".to_string())
}

DONTs

  • Dont Trust Env Strings Blindly: Never shove raw env values into headers.
// ❌ Bad
let token = format!("WezTerm/{}", std::env::var("WEZTERM_VERSION").unwrap());

// ✅ Good
let token = sanitize_header_value(&format!("WezTerm/{}", std::env::var("WEZTERM_VERSION").unwrap_or_default()));
  • Dont Duplicate Control Flow: Avoid multiple early returns that repeat logic.
// ❌ Bad
if !v.trim().is_empty() { return format!("WezTerm/{v}"); }
return "WezTerm".to_string();

// ✅ Good
return if !v.trim().is_empty() { format!("WezTerm/{v}") } else { "WezTerm".to_string() };
  • Dont Assume Presence ⇒ Validity: An env var can exist but be empty or whitespace.
// ❌ Bad
if let Ok(tp) = std::env::var("TERM_PROGRAM") {
    return tp; // might be empty/whitespace
}
  • Dont Change UA Shape Without Tests: Keep snapshot/regex tests in sync with header changes.
// ❌ Old pattern (missing terminal token)
let re = Regex::new(r"^codex_cli_rs/\d+\.\d+\.\d+ \(Mac OS \d+\.\d+\.\d+; (x86_64|arm64)\)$").unwrap();