Skip to content

shinjiyu/remote-console

Repository files navigation

Remote Console

A remote debugging SDK for WebView applications that cannot use Chrome/Safari DevTools.

Architecture

┌─────────────────┐     WebSocket     ┌─────────────────┐     WebSocket     ┌─────────────────┐
│   WebView App   │ ◄───────────────► │     Server      │ ◄───────────────► │   Web Console   │
│   (Client SDK)  │                   │   (Node.js)     │                   │    (React)      │
└─────────────────┘                   └─────────────────┘                   └─────────────────┘

Features

  • Client SDK: Intercepts console output, supports remote eval execution
  • Server: WebSocket relay server with session management
  • Web Console: Real-time log viewing and remote code execution

Quick Start (Local Development)

1. Install Dependencies

npm install

2. Build All Packages

npm run build

3. Start Services

# Terminal 1: Start server
npm run dev:server

# Terminal 2: Start web console
npm run dev:console

4. Access

  • Server: ws://localhost:3000
  • Web Console: http://localhost:8080

Production Deployment

部署分为两个部分:

  1. 服务部署 - 使用 Docker 运行服务
  2. 公网访问 - 选择 Nginx 或 Cloudflare Tunnel 暴露服务

Step 1: 使用 Docker 部署服务

# 构建并启动
docker-compose -f docker-compose.prod.yml up -d --build

# 查看日志
docker-compose -f docker-compose.prod.yml logs -f

# 停止服务
docker-compose -f docker-compose.prod.yml down

服务端口:

  • Server: localhost:3003
  • Web Console: localhost:8082

Step 2: 配置公网访问

选择以下任一方式将服务暴露到公网:

方式 A: Cloudflare Tunnel(推荐,最简单)

优点:无需公网 IP、自动 HTTPS、无需配置 Nginx

快速使用(无需登录)
# 安装 cloudflared
# macOS
brew install cloudflared

# Linux
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
chmod +x cloudflared && sudo mv cloudflared /usr/local/bin/

# 一键暴露服务(会生成临时域名)
cloudflared tunnel --url http://localhost:3003
# 输出类似: https://xxx-xxx-xxx.trycloudflare.com

# 另开终端,暴露 Web Console
cloudflared tunnel --url http://localhost:8082
持久化使用(需要 Cloudflare 账号)
# 登录
cloudflared tunnel login

# 创建隧道
cloudflared tunnel create remote-console

# 创建配置 ~/.cloudflared/config.yml
tunnel: <TUNNEL_ID>
credentials-file: ~/.cloudflared/<TUNNEL_ID>.json

ingress:
  - hostname: console.your-domain.com
    service: http://localhost:8082
  - hostname: ws.your-domain.com
    service: http://localhost:3003
  - service: http_status:404

# 添加 DNS 记录
cloudflared tunnel route dns remote-console console.your-domain.com
cloudflared tunnel route dns remote-console ws.your-domain.com

# 启动隧道
cloudflared tunnel run remote-console

方式 B: Nginx 反向代理

适用于有公网 IP 的服务器。

# Web Console
location /remote-console/ {
    proxy_pass http://127.0.0.1:8082/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# WebSocket
location /remote-console/ws {
    proxy_pass http://127.0.0.1:3003;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 86400;
}

# SDK 静态文件
location /remote-console/sdk/ {
    alias /path/to/remote-console/sdk/;
    add_header Access-Control-Allow-Origin *;
}
nginx -t && systemctl reload nginx

Step 3: 配置 SDK

根据你选择的公网访问方式,配置 SDK 连接地址。

如果你沿用本文档的 nginx 方案,实际 URL 结构应为:

  • SDK UMD(推荐兼容版): https://your-domain.com/remote-console/sdk/remote-console.legacy.umd.js
  • 条件加载器: https://your-domain.com/remote-console/sdk/conditional-loader.js
  • WebSocket: wss://your-domain.com/remote-console/ws
<script src="https://your-domain.com/remote-console/sdk/remote-console.legacy.umd.js"></script>
<script>
  RemoteConsole.init({
    serverUrl: 'wss://your-domain.com/remote-console/ws',
    name: 'My App'
  });
</script>

Authentication & Whitelist (新)

Remote Console 现在内置一层鉴权:Web Console(人类) 必须凭 loginserver 的账号登录,且邮箱在白名单中;MCP / 自动化 凭 API Token;SDK 上报日志不需要鉴权(自用场景)。

模型

浏览器 (cookie: rc_token)  ─┐
MCP / CI (rc-token.<TOKEN>) ─┼── nginx ─── remote-console-server ─── HTTPS ──> loginserver /api/auth/verify
设备端 SDK (无凭据)          ─┘                       │
                                                     └── 本地 JSON 白名单 + API tokens
  • 登录:浏览器 → POST /api/auth/login → 服务端转发到 loginserver /api/auth/login → 校验白名单 → 写 HttpOnly Cookie。
  • WS 鉴权upgrade 握手时读取 cookie 或子协议 rc-token.<TOKEN>,未通过的连接只能注册为 clientType: 'sdk'
  • 白名单:完全独立于 loginserver,由 admin 在 Web Console 「Admin」页面增删;磁盘存于 /data/auth.json(容器内)。
  • API Token:每个白名单用户可在 Web Console 「Tokens」页面自助生成;明文只显示一次,存储为 SHA-256 哈希。

配置

docker-compose.prod.yml 已加好持久化与环境变量。在仓库根目录用 .env 覆盖:

# .env (与 docker-compose.prod.yml 同目录)
ADMIN_EMAILS=you@example.com,partner@example.com
LOGIN_SERVER_URL=http://host.docker.internal:5001    # 同机 docker,loginserver 暴露 5001
COOKIE_SECURE=auto    # auto / always / never; nginx 终止 TLS 时一般 auto 即可

启动:

mkdir -p ./data/auth
docker-compose -f docker-compose.prod.yml up -d --build

启动日志会打印 [auth] seeded admin emails: ...。这些邮箱会被添加到白名单且 role=admin,但密码仍然在 loginserver 那边(用 shinjiyu/loginserver 提供的注册页面提前注册即可)。

Nginx(host 上的反向代理)

在原有 /remote-console//remote-console/ws 的基础上,新增一行 /remote-console/api/

location /remote-console/ {
    proxy_pass http://127.0.0.1:8082/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

# 新增:HTTP API(cookie 同源生效)
location /remote-console/api/ {
    proxy_pass http://127.0.0.1:3003/api/;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

location /remote-console/ws {
    proxy_pass http://127.0.0.1:3003;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_read_timeout 86400;
}

MCP 客户端

为 Cursor 配置 MCP 时增加 RC_API_TOKEN(在 Web Console「Tokens」页面生成):

{
  "mcpServers": {
    "remote-console": {
      "command": "npx",
      "args": ["-y", "remote-console-mcp"],
      "env": {
        "RC_SERVER_URL": "wss://your-domain.com/remote-console/ws",
        "RC_API_TOKEN":  "rct_<paste-token-here>"
      }
    }
  }
}

未配 RC_API_TOKEN 或 token 已被吊销时,MCP 端会收到 4401 关闭码并打印「token rejected; not reconnecting」。

关于 SDK

SDK 行为完全不变;不需要 token。不要把 MCP 用的 rct_... 暴露到任何 SDK 端代码或 HTML 中


SDK Usage

接到另一个项目

如果你的另一个项目是浏览器页面、H5、WebView 容器,最简单的接法就是直接引线上 兼容性更好的 legacy UMD

<script src="https://your-domain.com/remote-console/sdk/remote-console.legacy.umd.js"></script>
<script>
  RemoteConsole.init({
    // SDK 不需要登录,也不需要 token
    serverUrl: 'wss://your-domain.com/remote-console/ws',
    name: 'My Other Project'
  });
</script>

说明:

  • SDK 角色是匿名 sdk不走 loginserver,不需要白名单,不要塞任何 token
  • 真正需要登录的是 Web Console(人类)和 MCP(自动化)
  • name 建议填项目名 / 页面名,方便在 Web Console 里区分
  • sessionId 可不填;SDK 会自动生成,并额外持久化一个 deviceIdlocalStorage

如果你只想在测试环境开启,优先用下面的 conditional-loader.js 方案。

仅测试环境嵌入(推荐)

希望 只在测试/联调环境 加载 Remote Console,生产环境不加载、不连接。使用条件加载器即可,同一套 HTML/构建产物即可区分环境:

<!-- 使用条件加载器:仅当为测试环境时才加载并初始化 SDK -->
<script src="https://your-domain.com/remote-console/sdk/conditional-loader.js"
        data-remote-console-src="https://your-domain.com/remote-console/sdk/remote-console.legacy.umd.js"
        data-server-url="wss://your-domain.com/remote-console/ws"
        data-name="My App"></script>

测试环境判定(满足其一即加载):

  • window.REMOTE_CONSOLE_ENABLED === true(页面内可主动开启)
  • 当前 host 匹配:localhost127.0.0.1、含 test-s.alpha-s..test.-test.fproject

构建脚本会随 npm run build:sdkconditional-loader.jsremote-console.legacy.umd.js 等产物输出到 client-sdk/dist/,部署到 CDN 或静态目录即可。


Script Tag (Legacy UMD, 推荐)

<script src="https://your-domain.com/remote-console/sdk/remote-console.legacy.umd.js"></script>
<script>
  RemoteConsole.init({
    serverUrl: 'wss://your-domain.com/remote-console/ws',
    name: 'My App',           // Optional: display name
    sessionId: 'my-session',  // Optional: custom session ID
    autoConnect: true         // Optional: auto-connect on init
  });
</script>

ES Modules

import { RemoteConsole } from 'remote-console-sdk';

RemoteConsole.init({
  serverUrl: 'wss://your-domain.com/remote-console/ws',
  name: 'My App'
});

SDK API

RemoteConsole.init(config);      // Initialize
RemoteConsole.connect();         // Manual connect
RemoteConsole.disconnect();      // Disconnect
RemoteConsole.getSessionId();    // Get session ID
RemoteConsole.isConnected();     // Check status
RemoteConsole.destroy();         // Cleanup

Configuration Options

Option Type Default Description
serverUrl string required WebSocket server URL
sessionId string auto-generated Custom session identifier
name string - Display name for the session
autoConnect boolean true Auto-connect on initialization
reconnectInterval number 3000 Reconnection interval (ms)
maxReconnectAttempts number 10 Max reconnection attempts
heartbeatInterval number 30000 Heartbeat interval (ms)

如果你的运行环境已经确定是现代浏览器 / 新版 WebView,也可以继续用 remote-console.umd.js;但默认建议优先接 remote-console.legacy.umd.js,尤其是 Android 老 WebView、内嵌浏览器、历史业务壳环境。


Project Structure

remote_console/
├── client-sdk/          # Browser SDK
│   ├── src/
│   │   ├── index.ts
│   │   ├── console-interceptor.ts
│   │   ├── eval-executor.ts
│   │   └── websocket-client.ts
│   ├── loader/
│   │   └── conditional-loader.js   # 仅测试环境加载 SDK,build 时拷贝到 dist/
│   └── package.json
├── server/              # Node.js WebSocket server
│   ├── src/
│   │   ├── index.ts
│   │   ├── session-manager.ts
│   │   └── message-handler.ts
│   ├── Dockerfile
│   └── package.json
├── web-console/         # React debugging interface
│   ├── src/
│   │   ├── App.tsx
│   │   └── components/
│   ├── Dockerfile
│   ├── nginx.conf
│   └── package.json
├── docker-compose.yml        # Local development
├── docker-compose.prod.yml   # Production deployment
└── package.json

Development

Building Individual Packages

npm run build:server   # Build server
npm run build:sdk      # Build client SDK
npm run build:console  # Build web console

Testing

  1. Start the server: npm run dev:server
  2. Start web console: npm run dev:console
  3. Open test/index.html in a browser
  4. Open web console at http://localhost:8080
  5. Select the session and start debugging

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors