Make Codex HTTP identity explicit

This commit is contained in:
Owen Lin
2026-05-19 13:54:51 -07:00
parent 05b8ce4354
commit caaae96609
49 changed files with 476 additions and 303 deletions
+13 -7
View File
@@ -7,6 +7,7 @@ use codex_app_server_protocol::PluginInstallPolicy;
use codex_app_server_protocol::PluginInterface;
use codex_app_server_protocol::SkillInterface;
use codex_login::CodexAuth;
use codex_login::default_client::Originator;
use codex_login::default_client::build_reqwest_client;
use codex_plugin::PluginId;
use codex_utils_absolute_path::AbsolutePathBuf;
@@ -23,6 +24,11 @@ use url::Url;
mod remote_installed_plugin_sync;
mod share;
fn build_process_reqwest_client() -> reqwest::Client {
let originator = Originator::process_default();
build_reqwest_client(&originator)
}
pub use remote_installed_plugin_sync::RemoteInstalledPluginBundleSyncError;
pub use remote_installed_plugin_sync::RemoteInstalledPluginBundleSyncOutcome;
pub use remote_installed_plugin_sync::RemotePluginCacheMutationGuard;
@@ -782,7 +788,7 @@ pub async fn fetch_remote_plugin_skill_detail(
}
let url = remote_plugin_skill_detail_url(config, plugin_id, skill_name)?;
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.get(&url), auth)?;
let response: RemotePluginSkillDetailResponse = send_and_decode(request, &url).await?;
if response.plugin_id != plugin_id {
@@ -883,7 +889,7 @@ pub async fn install_remote_plugin(
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/{plugin_id}/install");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.post(&url), auth)?;
let response: RemotePluginMutationResponse = send_and_decode(request, &url).await?;
if response.id != plugin_id {
@@ -919,7 +925,7 @@ pub async fn uninstall_remote_plugin(
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/plugins/{plugin_id}/uninstall");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.post(&url), auth)?;
let response: RemotePluginMutationResponse = send_and_decode(request, &url).await?;
if response.id != plugin_id {
@@ -1252,7 +1258,7 @@ async fn get_remote_plugin_list_page(
) -> Result<RemotePluginListResponse, RemotePluginCatalogError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/list");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let mut request = authenticated_request(client.get(&url), auth)?;
request = request.query(&[("scope", scope.api_value())]);
request = request.query(&[("limit", REMOTE_PLUGIN_LIST_PAGE_LIMIT)]);
@@ -1269,7 +1275,7 @@ async fn get_remote_shared_workspace_plugins_page(
) -> Result<RemotePluginListResponse, RemotePluginCatalogError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/workspace/shared");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let mut request = authenticated_request(client.get(&url), auth)?;
request = request.query(&[("limit", REMOTE_PLUGIN_LIST_PAGE_LIMIT)]);
if let Some(page_token) = page_token {
@@ -1287,7 +1293,7 @@ async fn get_remote_plugin_installed_page(
) -> Result<RemotePluginInstalledResponse, RemotePluginCatalogError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/installed");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let mut request = authenticated_request(client.get(&url), auth)?;
request = request.query(&[("scope", scope.api_value())]);
if include_download_urls {
@@ -1307,7 +1313,7 @@ async fn fetch_plugin_detail(
) -> Result<RemotePluginDirectoryItem, RemotePluginCatalogError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/{plugin_id}");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let mut request = authenticated_request(client.get(&url), auth)?;
if include_download_urls {
request = request.query(&[("includeDownloadUrls", true)]);
+6 -7
View File
@@ -1,6 +1,5 @@
use super::*;
use codex_login::CodexAuth;
use codex_login::default_client::build_reqwest_client;
use codex_utils_absolute_path::AbsolutePathBuf;
use flate2::Compression;
use flate2::write::GzEncoder;
@@ -282,7 +281,7 @@ pub async fn delete_remote_plugin_share(
let auth = ensure_chatgpt_auth(auth)?;
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/public/plugins/workspace/{remote_plugin_id}");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.delete(&url), auth)?;
send_and_expect_status(request, &url, &[StatusCode::NO_CONTENT]).await?;
if let Err(err) = local_paths::remove_plugin_share_local_path(codex_home, remote_plugin_id) {
@@ -315,7 +314,7 @@ pub async fn update_remote_plugin_share_targets(
.unwrap_or_default();
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/{remote_plugin_id}/shares");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.put(&url), auth)?.json(
&RemotePluginShareUpdateTargetsRequest {
discoverability,
@@ -381,7 +380,7 @@ async fn get_created_workspace_plugins_page(
) -> Result<RemotePluginListResponse, RemotePluginCatalogError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/ps/plugins/workspace/created");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let mut request = authenticated_request(client.get(&url), auth)?;
request = request.query(&[("limit", REMOTE_PLUGIN_LIST_PAGE_LIMIT)]);
if let Some(page_token) = page_token {
@@ -399,7 +398,7 @@ async fn create_workspace_plugin_upload(
) -> Result<RemoteWorkspacePluginUploadUrlResponse, RemotePluginCatalogError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/public/plugins/workspace/upload-url");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.post(&url), auth)?.json(
&RemoteWorkspacePluginUploadUrlRequest {
filename,
@@ -415,7 +414,7 @@ async fn put_workspace_plugin_upload(
upload_url: &str,
archive_bytes: Vec<u8>,
) -> Result<(), RemotePluginCatalogError> {
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = client
.put(upload_url)
.timeout(REMOTE_PLUGIN_CATALOG_TIMEOUT)
@@ -453,7 +452,7 @@ async fn finalize_workspace_plugin_upload(
} else {
format!("{base_url}/public/plugins/workspace")
};
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = authenticated_request(client.post(&url), auth)?.json(&body);
send_and_decode(request, &url).await
}
+7 -1
View File
@@ -2,6 +2,7 @@ use crate::store::PluginInstallResult;
use crate::store::PluginStore;
use crate::store::PluginStoreError;
use crate::store::validate_plugin_version_segment;
use codex_login::default_client::Originator;
use codex_login::default_client::build_reqwest_client;
use codex_plugin::PluginId;
use codex_plugin::PluginIdError;
@@ -29,6 +30,11 @@ const REMOTE_PLUGIN_INSTALL_STAGING_DIR: &str = "plugins/.remote-plugin-install-
const TEST_ALLOW_LOOPBACK_HTTP_REMOTE_PLUGIN_BUNDLES_ENV: &str =
"CODEX_TEST_ALLOW_HTTP_REMOTE_PLUGIN_BUNDLE_DOWNLOADS";
fn build_process_reqwest_client() -> reqwest::Client {
let originator = Originator::process_default();
build_reqwest_client(&originator)
}
#[derive(Debug, Clone)]
pub struct ValidatedRemotePluginBundle {
pub plugin_id: PluginId,
@@ -263,7 +269,7 @@ async fn download_remote_plugin_bundle_with_limit(
bundle_download_url: &str,
max_bytes: u64,
) -> Result<Vec<u8>, RemotePluginBundleInstallError> {
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let response = client
.get(bundle_download_url)
.timeout(REMOTE_PLUGIN_BUNDLE_DOWNLOAD_TIMEOUT)
+9 -3
View File
@@ -1,5 +1,6 @@
use crate::remote::RemotePluginServiceConfig;
use codex_login::CodexAuth;
use codex_login::default_client::Originator;
use codex_login::default_client::build_reqwest_client;
use codex_protocol::protocol::Product;
use serde::Deserialize;
@@ -11,6 +12,11 @@ const REMOTE_PLUGIN_FETCH_TIMEOUT: Duration = Duration::from_secs(30);
const REMOTE_FEATURED_PLUGIN_FETCH_TIMEOUT: Duration = Duration::from_secs(10);
const REMOTE_PLUGIN_MUTATION_TIMEOUT: Duration = Duration::from_secs(30);
fn build_process_reqwest_client() -> reqwest::Client {
let originator = Originator::process_default();
build_reqwest_client(&originator)
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct RemotePluginStatusSummary {
pub name: String,
@@ -129,7 +135,7 @@ pub async fn fetch_remote_plugin_status(
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/plugins/list");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = client
.get(&url)
.timeout(REMOTE_PLUGIN_FETCH_TIMEOUT)
@@ -161,7 +167,7 @@ pub async fn fetch_remote_featured_plugin_ids(
) -> Result<Vec<String>, RemotePluginFetchError> {
let base_url = config.chatgpt_base_url.trim_end_matches('/');
let url = format!("{base_url}/plugins/featured");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let mut request = client
.get(&url)
.query(&[(
@@ -236,7 +242,7 @@ async fn post_remote_plugin_mutation(
) -> Result<RemotePluginMutationResponse, RemotePluginMutationError> {
let auth = ensure_codex_backend_auth(auth)?;
let url = remote_plugin_mutation_url(config, plugin_id, action)?;
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let request = client
.post(url.clone())
.timeout(REMOTE_PLUGIN_MUTATION_TIMEOUT)
+9 -3
View File
@@ -13,6 +13,7 @@ use tempfile::TempDir;
use tracing::warn;
use zip::ZipArchive;
use codex_login::default_client::Originator;
use codex_login::default_client::build_reqwest_client;
const GITHUB_API_BASE_URL: &str = "https://api.github.com";
@@ -31,6 +32,11 @@ const CURATED_PLUGINS_BACKUP_ARCHIVE_TIMEOUT: Duration = Duration::from_secs(30)
// Keep this comfortably above a normal sync attempt so we do not race another Codex process.
const CURATED_PLUGINS_STALE_TEMP_DIR_MAX_AGE: Duration = Duration::from_secs(10 * 60);
fn build_process_reqwest_client() -> Client {
let originator = Originator::process_default();
build_reqwest_client(&originator)
}
#[derive(Debug, Deserialize)]
struct GitHubRepositorySummary {
default_branch: String,
@@ -590,7 +596,7 @@ fn ensure_git_success(output: &Output, context: &str) -> Result<(), String> {
async fn fetch_curated_repo_remote_sha(api_base_url: &str) -> Result<String, String> {
let api_base_url = api_base_url.trim_end_matches('/');
let repo_url = format!("{api_base_url}/repos/{OPENAI_PLUGINS_OWNER}/{OPENAI_PLUGINS_REPO}");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let repo_body = fetch_github_text(&client, &repo_url, "get curated plugins repository").await?;
let repo_summary: GitHubRepositorySummary =
serde_json::from_str(&repo_body).map_err(|err| {
@@ -624,14 +630,14 @@ async fn fetch_curated_repo_zipball(
let api_base_url = api_base_url.trim_end_matches('/');
let repo_url = format!("{api_base_url}/repos/{OPENAI_PLUGINS_OWNER}/{OPENAI_PLUGINS_REPO}");
let zipball_url = format!("{repo_url}/zipball/{remote_sha}");
let client = build_reqwest_client();
let client = build_process_reqwest_client();
fetch_github_bytes(&client, &zipball_url, "download curated plugins archive").await
}
async fn fetch_curated_repo_backup_archive_zip(
backup_archive_api_url: &str,
) -> Result<Vec<u8>, String> {
let client = build_reqwest_client();
let client = build_process_reqwest_client();
let export_body = fetch_public_text(
&client,
backup_archive_api_url,