Skip to content

fix(#671): proxy WebSocket upgrades to External Apps#672

Merged
Kewton merged 1 commit intodevelopfrom
feature/671-worktree
Apr 20, 2026
Merged

fix(#671): proxy WebSocket upgrades to External Apps#672
Kewton merged 1 commit intodevelopfrom
feature/671-worktree

Conversation

@Kewton
Copy link
Copy Markdown
Owner

@Kewton Kewton commented Apr 20, 2026

Summary

  • src/lib/ws-server.ts の upgrade ハンドラに /proxy/<prefix>/... 分岐を追加し、external_apps レコードが enabled=1 & websocket_enabled=1 の場合は upstream へ raw TCP で WebSocket をパススルー (handleProxyUpgrade() を DI 構成で実装)
  • SSRF 防御: PROXY_ALLOWED_HOSTS = {'localhost', '127.0.0.1'} allow-list
  • 補助対応: proxyWebSocket()@deprecated 化、/proxy/[...path]/route.tsHEAD 追加、next.config.jsskipTrailingSlashRedirect: true

これにより Streamlit / Shiny 等 WebSocket を必要とする External App が CommandMate プロキシ越しでも完全にインタラクティブに起動するようになる。

Closes #671

Test plan

  • npm run lint Pass
  • npx tsc --noEmit Pass
  • npm run test:unit Pass (337 files / 6342 passed / 7 skipped)
  • npm run build Pass
  • 新規 tests/unit/ws-server-proxy-upgrade.test.ts 11 ケース pass
  • 既存 tests/integration/websocket.test.ts リグレッション無し
  • live Streamlit (Photon) を /proxy/photon/ で開いて完全にインタラクティブに動作することを手動確認 (developマージ後)

受け入れ基準 (Issue #671)

  • AC-1: /proxy/<prefix>/_stcore/stream への WS Upgrade が upstream Streamlit に到達 (再現コマンドで上流フレームが流れる)
  • AC-2: CommandMate 内蔵 WS (Terminal/Subscribe/Broadcast) のリグレッション無し
  • AC-3: enabled=0 または websocket_enabled=0 の External App への WS Upgrade は 4xx で拒否
  • AC-4: SSRF 防御 (allow-list)
  • AC-5: 既存 tests/integration/websocket.test.ts pass
  • AC-6: HEAD メソッドが 200 / 適切なステータスを返す
  • AC-7: trailing slash 抑止
  • AC-8: lint / tsc / unit / build all green
  • AC-9: SSRF / 認証 / IP 制限のチェック順序を踏襲
  • AC-10: upstream 切断時にクライアント socket を確実に破棄

🤖 Generated with Claude Code

`src/lib/ws-server.ts` の upgrade ハンドラに `/proxy/<prefix>/...` 分岐を追加し、
対応する external_apps レコードが enabled かつ websocket_enabled の場合は
upstream へ raw TCP で WebSocket をパススルーするようにした。これにより
Streamlit/Shiny 等 WebSocket を使う External App が CommandMate プロキシ越しでも
完全に起動できるようになる。

主な変更:
- src/lib/ws-server.ts: handleProxyUpgrade() を DI 構成で実装し、`/proxy/<prefix>` を
  upstream 解決→TCP 接続→双方向パイプ
- SSRF 防御: PROXY_ALLOWED_HOSTS = {'localhost', '127.0.0.1'} allow-list
- src/lib/proxy/handler.ts: 旧 proxyWebSocket() を @deprecated 化 (実際には
  Route Handler に upgrade は到達しないため dead code)
- src/app/proxy/[...path]/route.ts: HEAD メソッドを追加 (ヘルスチェック向け)
- next.config.js: skipTrailingSlashRedirect: true を設定し
  `/proxy/<prefix>/` の 308 を抑止
- tests/unit/ws-server-proxy-upgrade.test.ts (11 ケース) と
  tests/unit/proxy/route.test.ts (HEAD ケース) を追加

品質: lint / tsc / 6342 unit / 179 regression すべて pass。
新規コードパスのカバレッジ ~92%。

Closes #671

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Kewton Kewton merged commit 123db5b into develop Apr 20, 2026
5 checks passed
@Kewton Kewton deleted the feature/671-worktree branch April 20, 2026 00:23
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.

1 participant