Skip to content

Conversation

@whoiskatrin
Copy link
Collaborator

@whoiskatrin whoiskatrin commented Oct 28, 2025

adds WebSocket support to the Sandbox SDK. we added connect(sandbox, request, port) to route client WebSocket connections directly to WebSocket servers in containers.


 // Route incoming WebSocket request to container service
  const sandbox = getSandbox(env.Sandbox, sandboxId);
  return await connect(sandbox, request, 8080);

How it works:

  1. Start a WebSocket server inside the container (Bun, Node.js, Python, etc.)
  2. Use connect() to route incoming WebSocket upgrade requests
  3. Client communicates directly with the container's WebSocket server

Adding PR to docs repo for this: cloudflare/cloudflare-docs#26133

@changeset-bot
Copy link

changeset-bot bot commented Oct 28, 2025

🦋 Changeset detected

Latest commit: 39f6dd8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/sandbox Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@claude
Copy link

claude bot commented Oct 28, 2025

Claude Code Review

WebSocket Support Implementation - Looks Good

The PR successfully adds WebSocket support via the connect() function. Architecture and implementation are solid.

Issues Found

1. Incomplete Error Handling in Test Worker (packages/sandbox/src/sandbox.ts:206-214)

The WebSocket routing in the test worker lacks error handling for unknown paths:

if (upgradeHeader?.toLowerCase() === 'websocket') {
  if (url.pathname === '/ws/echo') {
    return await connect(sandbox, request, 8080);
  }
  if (url.pathname === '/ws/code') {
    return await connect(sandbox, request, 8081);
  }
  if (url.pathname === '/ws/terminal') {
    return await connect(sandbox, request, 8082);
  }
}

Issue: If a WebSocket request hits an unrecognized path, it falls through to the end of the handler without returning a proper error response.

Fix: Add a catch-all for unrecognized WebSocket paths:

if (upgradeHeader?.toLowerCase() === 'websocket') {
  if (url.pathname === '/ws/echo') return await connect(sandbox, request, 8080);
  if (url.pathname === '/ws/code') return await connect(sandbox, request, 8081);
  if (url.pathname === '/ws/terminal') return await connect(sandbox, request, 8082);
  
  // Unknown WebSocket endpoint
  return new Response('WebSocket endpoint not found', { status: 404 });
}

2. Race Condition in E2E Tests (tests/e2e/websocket-connect.test.ts:46-47)

await new Promise(resolve => setTimeout(resolve, 2000));

Issue: Hard-coded 2-second sleep assumes server startup completes. On slower CI runners or during cold starts, this could cause flaky tests.

Better approach: Poll the server health or add a readiness check:

// Wait for server to be ready (with retry)
for (let i = 0; i < 10; i++) {
  const processes = await fetch(`${workerUrl}/api/processes/list`, { headers }).then(r => r.json());
  if (processes.processes?.some(p => p.id === 'ws-echo-8080' && p.status === 'running')) {
    await new Promise(resolve => setTimeout(resolve, 500)); // Grace period
    break;
  }
  await new Promise(resolve => setTimeout(resolve, 500));
}

3. Container.fetch() Type Safety (packages/sandbox/src/sandbox.ts:321)

return await super.fetch(request);

The super.fetch() call bypasses containerFetch() which means it skips JSRPC and goes directly to the Container base class. This is correct for WebSockets but the comment could be clearer about the architectural implications.

Suggestion: Enhance the comment:

// WebSocket path: Let parent Container class handle WebSocket proxying
// This bypasses containerFetch() which uses JSRPC and cannot handle WebSocket upgrades.
// The Container base class proxies directly to the container HTTP server, preserving
// the WebSocket upgrade handshake that would be broken by JSRPC serialization.

Minor Observations

  1. Good: Port validation with validatePort() prevents privileged port access (packages/sandbox/src/sandbox.ts:83-86)
  2. Good: Comprehensive unit tests covering WebSocket detection, routing, and error cases
  3. Good: E2E tests verify actual WebSocket connections, not just mocked behavior
  4. Good: The standalone connect() function design correctly avoids DO RPC serialization issues

Testing Coverage

✅ Unit tests cover WebSocket detection logic
✅ E2E tests verify actual container connections
✅ Port validation tests included
✅ Concurrent connection tests included

Verdict

Approve with minor improvements suggested. The WebSocket implementation is architecturally sound and well-tested. The identified issues are minor (test robustness and error handling) but should be addressed to prevent flaky tests and improve error visibility.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 28, 2025

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/sandbox-sdk/@cloudflare/sandbox@162

commit: b915e85

@github-actions
Copy link
Contributor

github-actions bot commented Oct 28, 2025

🐳 Docker Image Published

FROM cloudflare/sandbox:0.0.0-pr-162-b2c49a7

Version: 0.0.0-pr-162-b2c49a7

You can use this Docker image with the preview package from this PR.

@whoiskatrin whoiskatrin marked this pull request as ready for review October 28, 2025 21:43
ghostwriternr and others added 7 commits October 29, 2025 11:53
The examples/basic directory was primarily used for integration testing
rather than as a standalone example. This moves it to tests/integration
to reflect its actual purpose.

Merged WebSocket example functionality into tests/integration since it
shared the same testing infrastructure. Simplified WebSocket E2E tests
by removing redundant test coverage and focusing on core transport-level
functionality.
This reverts commit b915e85.
@ghostwriternr ghostwriternr enabled auto-merge (squash) October 29, 2025 16:45
@ghostwriternr ghostwriternr merged commit c4db459 into main Oct 29, 2025
8 of 9 checks passed
@threepointone threepointone mentioned this pull request Oct 29, 2025
@ghostwriternr ghostwriternr deleted the websockets-support branch October 29, 2025 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants