mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Preserve remote plugin download status errors (#28863)
## Summary - preserve the original HTTP status when a remote plugin bundle download returns a non-success response - retain at most 8 KiB of the error response body and annotate truncation or body-read failures - add regression coverage for an oversized error response ## Root cause The non-success response path reused the normal size-limited body reader. When an error response exceeded 8 KiB, that reader returned `DownloadTooLarge` before the code constructed `DownloadStatus`, masking the upstream HTTP status and response context. ## Impact Remote plugin installation failures now retain the actionable upstream HTTP status without allowing unbounded error bodies into logs. ## Validation - `just test -p codex-app-server plugin_install_preserves_status_when_remote_bundle_error_body_is_too_large` - `just fmt` - `git diff --check`
This commit is contained in:
committed by
GitHub
Unverified
parent
4af7762f01
commit
406062c3af
@@ -1010,15 +1010,12 @@ async fn plugin_install_tracks_remote_plugin_analytics_event() -> Result<()> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn plugin_install_errors_when_remote_bundle_download_fails() -> Result<()> {
|
||||
async fn plugin_install_preserves_status_when_remote_bundle_error_body_is_too_large() -> Result<()>
|
||||
{
|
||||
let codex_home = TempDir::new()?;
|
||||
let server = MockServer::start().await;
|
||||
let bundle_url = mount_remote_plugin_bundle(
|
||||
&server,
|
||||
/*status_code*/ 503,
|
||||
b"bundle temporarily unavailable".to_vec(),
|
||||
)
|
||||
.await;
|
||||
let bundle_url =
|
||||
mount_remote_plugin_bundle(&server, /*status_code*/ 503, vec![b'x'; 8 * 1024 + 1]).await;
|
||||
configure_remote_plugin_test(codex_home.path(), &server)?;
|
||||
mount_remote_plugin_detail(&server, REMOTE_PLUGIN_ID, "1.2.3", Some(&bundle_url)).await;
|
||||
mount_empty_remote_installed_plugins(&server).await;
|
||||
@@ -1041,6 +1038,20 @@ async fn plugin_install_errors_when_remote_bundle_download_fails() -> Result<()>
|
||||
|
||||
assert_eq!(err.error.code, -32603);
|
||||
assert!(err.error.message.contains("failed with status 503"));
|
||||
assert!(
|
||||
err.error
|
||||
.message
|
||||
.contains("[response body truncated after 8192 bytes]")
|
||||
);
|
||||
assert_eq!(
|
||||
err.error
|
||||
.message
|
||||
.bytes()
|
||||
.filter(|byte| *byte == b'x')
|
||||
.count(),
|
||||
8192
|
||||
);
|
||||
assert!(!err.error.message.contains("exceeded maximum size"));
|
||||
wait_for_remote_plugin_request_count(
|
||||
&server,
|
||||
"GET",
|
||||
|
||||
@@ -293,13 +293,37 @@ async fn download_remote_plugin_bundle_with_limit(
|
||||
let url = final_url.to_string();
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
let body = read_response_body_with_limit(
|
||||
response,
|
||||
&url,
|
||||
/*max_bytes*/ REMOTE_PLUGIN_BUNDLE_ERROR_BODY_MAX_BYTES,
|
||||
)
|
||||
.await?;
|
||||
let body = String::from_utf8_lossy(&body).to_string();
|
||||
let mut response = response;
|
||||
let mut body = Vec::new();
|
||||
let mut body_truncated = false;
|
||||
let mut body_read_error = None;
|
||||
loop {
|
||||
let chunk = match response.chunk().await {
|
||||
Ok(Some(chunk)) => chunk,
|
||||
Ok(None) => break,
|
||||
Err(source) => {
|
||||
body_read_error = Some(source);
|
||||
break;
|
||||
}
|
||||
};
|
||||
let remaining = REMOTE_PLUGIN_BUNDLE_ERROR_BODY_MAX_BYTES as usize - body.len();
|
||||
if chunk.len() > remaining {
|
||||
body.extend_from_slice(&chunk[..remaining]);
|
||||
body_truncated = true;
|
||||
break;
|
||||
}
|
||||
body.extend_from_slice(&chunk);
|
||||
}
|
||||
|
||||
let mut body = String::from_utf8_lossy(&body).into_owned();
|
||||
if body_truncated {
|
||||
body.push_str(&format!(
|
||||
"\n[response body truncated after {REMOTE_PLUGIN_BUNDLE_ERROR_BODY_MAX_BYTES} bytes]"
|
||||
));
|
||||
}
|
||||
if let Some(source) = body_read_error {
|
||||
body.push_str(&format!("\n[failed to read response body: {source}]"));
|
||||
}
|
||||
return Err(RemotePluginBundleInstallError::DownloadStatus { url, status, body });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user