跳转到内容
搜索文档

终端

最后更新 查看 MarkdownAgent 设置

通过 WebSocket 将基于浏览器的终端 UI 连接到沙箱 shell。服务端的 terminal() 方法将 WebSocket 连接代理到容器,客户端的 SandboxAddon 与 xterm.js 集成以进行终端渲染。

服务端方法

terminal()

代理 WebSocket 升级请求以创建终端连接。

const response = await sandbox.terminal(request: Request, options?: PtyOptions): Promise<Response>

参数

  • request - 来自浏览器的 WebSocket 升级请求(必须包含 Upgrade: websocket 标头)
  • options(可选):
    • cols - 终端宽度(列数,默认:80
    • rows - 终端高度(行数,默认:24

返回值Promise<Response> — WebSocket 升级响应

// In your Worker's fetch handler
return await sandbox.terminal(request, { cols: 120, rows: 30 });
// In your Worker's fetch handler
return await sandbox.terminal(request, { cols: 120, rows: 30 });

适用于默认会话与显式创建的会话

// Default session
return await sandbox.terminal(request);

// Specific session
const session = await sandbox.getSession("dev");
return await session.terminal(request);
// Default session
return await sandbox.terminal(request);

// Specific session
const session = await sandbox.getSession('dev');
return await session.terminal(request);

客户端 addon

@cloudflare/sandbox/xterm 模块为 xterm.js 提供 SandboxAddon,负责处理 WebSocket 连接、重连以及终端尺寸调整转发。

SandboxAddon

import { SandboxAddon } from '@cloudflare/sandbox/xterm';

const addon = new SandboxAddon(options: SandboxAddonOptions);

选项

  • getWebSocketUrl(params) - 为每次连接尝试构建 WebSocket URL。接收:
    • sandboxId - 目标沙箱 ID
    • sessionId(可选)- 目标会话 ID
    • origin - 从 window.location 派生的 WebSocket origin(例如 wss://example.com
  • reconnect - 启用带指数退避的自动重连(默认:true
  • onStateChange(state, error?) - 连接状态变更的回调
import { Terminal } from "@xterm/xterm";
import { SandboxAddon } from "@cloudflare/sandbox/xterm";

const terminal = new Terminal({ cursorBlink: true });
terminal.open(document.getElementById("terminal"));

const addon = new SandboxAddon({
	getWebSocketUrl: ({ sandboxId, sessionId, origin }) => {
		const params = new URLSearchParams({ id: sandboxId });
		if (sessionId) params.set("session", sessionId);
		return `${origin}/ws/terminal?${params}`;
	},
	onStateChange: (state, error) => {
		console.log(`Terminal ${state}`, error);
	},
});

terminal.loadAddon(addon);
addon.connect({ sandboxId: "my-sandbox" });
import { Terminal } from '@xterm/xterm';
import { SandboxAddon } from '@cloudflare/sandbox/xterm';

const terminal = new Terminal({ cursorBlink: true });
terminal.open(document.getElementById('terminal'));

const addon = new SandboxAddon({
  getWebSocketUrl: ({ sandboxId, sessionId, origin }) => {
    const params = new URLSearchParams({ id: sandboxId });
    if (sessionId) params.set('session', sessionId);
    return `${origin}/ws/terminal?${params}`;
  },
  onStateChange: (state, error) => {
    console.log(`Terminal ${state}`, error);
  }
});

terminal.loadAddon(addon);
addon.connect({ sandboxId: 'my-sandbox' });

connect()

建立与沙箱终端的连接。

addon.connect(target: ConnectionTarget): void

参数

  • target
    • sandboxId - 要连接的沙箱
    • sessionId(可选)- 沙箱内的会话

使用新目标调用 connect() 会断开当前目标并连接到新目标。在已连接时使用相同目标调用则无操作。

disconnect()

关闭连接并停止任何重连尝试。

addon.disconnect(): void

属性

属性 类型 描述
state 'disconnected' | 'connecting' | 'connected' 当前连接状态
sandboxId string | undefined 当前沙箱 ID
sessionId string | undefined 当前会话 ID

WebSocket 协议

SandboxAddon 会自动处理 WebSocket 协议。以下细节适用于不使用 addon 构建自定义终端客户端的场景。完整示例请参阅不使用 xterm.js 连接

连接生命周期

  1. 客户端向你的 Worker 端点打开 WebSocket。将 binaryType 设为 arraybuffer
  2. 服务端将先前连接的任何缓冲输出以二进制帧回放。这可能在 ready 消息之前到达。
  3. 服务端发送 ready 状态消息 — 终端现在接受输入。
  4. 二进制帧双向流动:客户端发送 UTF-8 编码的按键,服务端发送终端输出(包括 ANSI 转义序列)。
  5. 如果客户端断开连接,PTY 保持存活。重新连接到同一会话会回放缓冲输出,使终端看起来未改变。

控制消息(客户端到服务端)

发送 JSON 文本帧以控制终端。

Resize — 更新终端尺寸(colsrows 都必须为正数):

{ "type": "resize", "cols": 120, "rows": 30 }

状态消息(服务端到客户端)

服务端为生命周期事件发送 JSON 文本帧。

Ready — PTY 已初始化。缓冲输出(如有)已发送:

{ "type": "ready" }

Exit — shell 进程已终止:

{ "type": "exit", "code": 0, "signal": "SIGTERM" }

Error — 发生错误(例如无效控制消息或会话未找到):

{ "type": "error", "message": "Session not found" }

类型

interface PtyOptions {
	cols?: number;
	rows?: number;
}

type ConnectionState = "disconnected" | "connecting" | "connected";

interface ConnectionTarget {
	sandboxId: string;
	sessionId?: string;
}

interface SandboxAddonOptions {
	getWebSocketUrl: (params: {
		sandboxId: string;
		sessionId?: string;
		origin: string;
	}) => string;
	reconnect?: boolean;
	onStateChange?: (state: ConnectionState, error?: Error) => void;
}

相关资源

这篇文档对您有帮助吗?