mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Update unix socket transport to use WebSocket upgrade (#19244)
## Summary - Switch Unix socket app-server connections to perform the standard WebSocket HTTP Upgrade handshake - Update the Unix socket test to exercise a real upgrade over the Unix stream - Refresh the app-server README to describe the new Unix socket behavior ## Testing - `cargo test -p codex-app-server transport::unix_socket_tests` - `just fmt` - `git diff --check`
This commit is contained in:
committed by
GitHub
Unverified
parent
a3cccbd8ed
commit
687c5d9081
@@ -25,7 +25,7 @@ Supported transports:
|
||||
|
||||
- stdio (`--listen stdio://`, default): newline-delimited JSON (JSONL)
|
||||
- websocket (`--listen ws://IP:PORT`): one JSON-RPC message per websocket text frame (**experimental / unsupported**)
|
||||
- unix socket (`--listen unix://` or `--listen unix://PATH`): websocket frames over `$CODEX_HOME/app-server-control/app-server-control.sock` or a custom socket path without HTTP upgrade
|
||||
- unix socket (`--listen unix://` or `--listen unix://PATH`): websocket connections over `$CODEX_HOME/app-server-control/app-server-control.sock` or a custom socket path, using the standard HTTP Upgrade handshake
|
||||
- off (`--listen off`): do not expose a local transport
|
||||
|
||||
When running with `--listen ws://IP:PORT`, the same listener also serves basic HTTP health probes:
|
||||
@@ -39,7 +39,7 @@ Websocket transport is currently experimental and unsupported. Do not rely on it
|
||||
The unix socket transport is intended for local app-server control-plane clients. `codex app-server proxy`
|
||||
opens exactly one raw stream connection to `$CODEX_HOME/app-server-control/app-server-control.sock`
|
||||
by default, or to `--sock PATH` when provided, and proxies bytes between that socket and stdin/stdout.
|
||||
The socket uses websocket framing directly over the Unix socket, without an HTTP upgrade handshake.
|
||||
The proxied stream carries the websocket HTTP Upgrade handshake followed by websocket frames.
|
||||
|
||||
Security note:
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ use futures::StreamExt;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio::time::Duration;
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
use tokio_tungstenite::tungstenite::protocol::Role;
|
||||
use tokio_tungstenite::accept_async;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::error;
|
||||
use tracing::info;
|
||||
@@ -76,8 +75,13 @@ async fn run_control_socket_acceptor(
|
||||
|
||||
let transport_event_tx = transport_event_tx.clone();
|
||||
tokio::spawn(async move {
|
||||
let websocket_stream =
|
||||
WebSocketStream::from_raw_socket(stream, Role::Server, None).await;
|
||||
let websocket_stream = match accept_async(stream).await {
|
||||
Ok(websocket_stream) => websocket_stream,
|
||||
Err(err) => {
|
||||
warn!("failed to upgrade control socket websocket connection: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let (websocket_writer, websocket_reader) = websocket_stream.split();
|
||||
run_websocket_connection(websocket_writer, websocket_reader, transport_event_tx).await;
|
||||
});
|
||||
|
||||
@@ -16,10 +16,9 @@ use std::path::Path;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
use tokio_tungstenite::WebSocketStream;
|
||||
use tokio_tungstenite::client_async;
|
||||
use tokio_tungstenite::tungstenite::Bytes;
|
||||
use tokio_tungstenite::tungstenite::Message as WebSocketMessage;
|
||||
use tokio_tungstenite::tungstenite::protocol::Role;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
#[test]
|
||||
@@ -54,7 +53,7 @@ fn listen_unix_socket_accepts_relative_custom_path() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn control_socket_acceptor_forwards_websocket_text_messages_and_pings() {
|
||||
async fn control_socket_acceptor_upgrades_and_forwards_websocket_text_messages_and_pings() {
|
||||
let temp_dir = tempfile::TempDir::new().expect("temp dir");
|
||||
let socket_path = test_socket_path(temp_dir.path());
|
||||
let (transport_event_tx, mut transport_event_rx) =
|
||||
@@ -71,7 +70,10 @@ async fn control_socket_acceptor_forwards_websocket_text_messages_and_pings() {
|
||||
let stream = connect_to_socket(socket_path.as_path())
|
||||
.await
|
||||
.expect("client should connect");
|
||||
let mut websocket = WebSocketStream::from_raw_socket(stream, Role::Client, None).await;
|
||||
let (mut websocket, response) = client_async("ws://localhost/rpc", stream)
|
||||
.await
|
||||
.expect("websocket upgrade should complete");
|
||||
assert_eq!(response.status().as_u16(), 101);
|
||||
|
||||
let opened = timeout(Duration::from_secs(1), transport_event_rx.recv())
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user