mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[2/4] Implement executor HTTP request runner (#18582)
### Why Remote streamable HTTP MCP needs the executor to perform ordinary HTTP requests on the executor side. This keeps network placement aligned with `experimental_environment = "remote"` without adding MCP-specific executor APIs. ### What - Add an executor-side `http/request` runner backed by `reqwest`. - Validate request method and URL scheme, preserving the transport boundary at plain HTTP. - Return buffered responses for ordinary calls and emit ordered `http/request/bodyDelta` notifications for streaming responses. - Register the request handler in the exec-server router. - Document the runner entrypoint, conversion helpers, body-stream bridge, notification sender, timeout behavior, and new integration-test helpers. - Add exec-server integration tests with the existing websocket harness and a local TCP HTTP peer for buffered and streamed responses, with comments spelling out what each test proves and its setup/exercise/assert phases. ### Stack 1. #18581 protocol 2. #18582 runner 3. #18583 RMCP client 4. #18584 manager wiring and local/remote coverage ### Verification - `just fmt` - `cargo check -p codex-exec-server -p codex-rmcp-client --tests` - `cargo check -p codex-core --test all` compile-only - `git diff --check` - Online full CI is running from the `full-ci` branch, including the remote Rust test job. Co-authored-by: Codex <noreply@openai.com> --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -286,15 +286,19 @@ pub struct HttpRequestParams {
|
||||
/// Optional request body bytes.
|
||||
#[serde(default, rename = "bodyBase64")]
|
||||
pub body: Option<ByteChunk>,
|
||||
/// Optional request timeout in milliseconds.
|
||||
#[serde(default)]
|
||||
/// Request timeout in milliseconds.
|
||||
///
|
||||
/// Omitted or `null` disables the timeout. A number applies that exact
|
||||
/// millisecond deadline.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub timeout_ms: Option<u64>,
|
||||
/// Caller-chosen stream id for `http/request/bodyDelta` notifications.
|
||||
///
|
||||
/// The id must remain unique on a connection until the terminal body delta
|
||||
/// arrives, even if the caller stops reading the stream earlier.
|
||||
#[serde(default)]
|
||||
pub request_id: Option<String>,
|
||||
/// arrives, even if the caller stops reading the stream earlier. Buffered
|
||||
/// requests still send an id so callers can keep one consistent request
|
||||
/// envelope shape.
|
||||
pub request_id: String,
|
||||
/// Return after response headers and stream the response body as deltas.
|
||||
#[serde(default)]
|
||||
pub stream_response: bool,
|
||||
@@ -391,3 +395,49 @@ mod base64_bytes {
|
||||
.map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::HttpRequestParams;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn http_request_timeout_treats_omitted_and_null_as_no_timeout() {
|
||||
let omitted: HttpRequestParams = serde_json::from_value(serde_json::json!({
|
||||
"method": "GET",
|
||||
"url": "https://example.test",
|
||||
"requestId": "req-omitted-timeout",
|
||||
}))
|
||||
.expect("omitted timeout should deserialize");
|
||||
let null_timeout: HttpRequestParams = serde_json::from_value(serde_json::json!({
|
||||
"method": "GET",
|
||||
"url": "https://example.test",
|
||||
"requestId": "req-null-timeout",
|
||||
"timeoutMs": null,
|
||||
}))
|
||||
.expect("null timeout should deserialize");
|
||||
let explicit_timeout: HttpRequestParams = serde_json::from_value(serde_json::json!({
|
||||
"method": "GET",
|
||||
"url": "https://example.test",
|
||||
"requestId": "req-explicit-timeout",
|
||||
"timeoutMs": 1234,
|
||||
}))
|
||||
.expect("numeric timeout should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
(omitted.request_id.as_str(), omitted.timeout_ms),
|
||||
("req-omitted-timeout", None)
|
||||
);
|
||||
assert_eq!(
|
||||
(null_timeout.request_id.as_str(), null_timeout.timeout_ms),
|
||||
("req-null-timeout", None)
|
||||
);
|
||||
assert_eq!(
|
||||
(
|
||||
explicit_timeout.request_id.as_str(),
|
||||
explicit_timeout.timeout_ms
|
||||
),
|
||||
("req-explicit-timeout", Some(1234))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user