Skip to content

Commit cff897e

Browse files
authored
docs(sandbox): add sandbox proxy user guide #1083 (#1084)
* docs(sandbox): add sandbox proxy user guide Document the HTTP/WebSocket proxy endpoints exposed by ROCK Admin, including target-port selection (path/header/query), port restrictions, and error handling. Provided in both English and Chinese (zh-Hans). * fix express * opt format * opt format
1 parent 2344842 commit cff897e

3 files changed

Lines changed: 305 additions & 1 deletion

File tree

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
sidebar_position: 6
3+
---
4+
5+
# 沙箱代理 (Sandbox Proxy)
6+
7+
ROCK Admin 提供了一层代理能力,可以让你**从集群外部**访问运行在沙箱**内部**的服务,而无需为每个沙箱单独分配公网地址。代理支持两种传输模式:
8+
9+
| 模式 | 接入路径 | 适用场景 |
10+
|------|---------|---------|
11+
| HTTP 代理 | `/sandboxes/:sandbox_id/proxy/...` | REST API、Web UI、文件下载等任何 HTTP/1.1 流量 |
12+
| WebSocket 代理 | `ws(s)://.../sandboxes/:sandbox_id/proxy/...` | 实时通道、流式输出、浏览器端 WS 客户端 |
13+
14+
两种模式都通过 `sandbox_id` 路由。沙箱本身**不需要**公网 IP — Admin 负责接收客户端请求,并将其转发到集群内对应的运行时实例。
15+
16+
---
17+
18+
## 1. HTTP 代理
19+
20+
将任意 HTTP 请求转发到沙箱内部的服务。
21+
22+
### 接入路径
23+
24+
```text
25+
方法 (Methods) : GET | POST | PUT | DELETE | PATCH | HEAD | OPTIONS
26+
URL : $ROCK_BASE_URL/sandboxes/:sandbox_id/proxy[/:path]
27+
```
28+
29+
- 请求方法、请求头、查询字符串和请求体会原样转发到目标服务。
30+
- 目标服务的响应(状态码、响应头、响应体)会被流式回传给客户端。
31+
32+
### 指定目标端口
33+
34+
代理需要知道要访问沙箱内的哪个端口。共有三种方式可以指定 — **只能选其一**,同时使用多种方式会返回 `400 Bad Request`
35+
36+
| 优先级 | 指定方式 | 示例 |
37+
|--------|---------|------|
38+
| 1 | **路径前缀** | `/sandboxes/abc/proxy/port/8080/api/users` |
39+
| 2 | **请求头** | `X-ROCK-Target-Port: 8080` |
40+
| 3 | **查询参数** | `?rock_target_port=8080` |
41+
42+
如果不指定目标端口,请求会被路由到沙箱的默认服务端口。
43+
44+
### 使用示例
45+
46+
```bash
47+
# 通过路径方式指定端口
48+
curl -X POST \
49+
"$ROCK_BASE_URL/sandboxes/sb-123/proxy/port/8080/v1/predict" \
50+
-H "Content-Type: application/json" \
51+
-d '{"prompt": "hello"}'
52+
53+
# 通过请求头方式指定端口
54+
curl -X POST \
55+
"$ROCK_BASE_URL/sandboxes/sb-123/proxy/v1/predict" \
56+
-H "X-ROCK-Target-Port: 8080" \
57+
-H "Content-Type: application/json" \
58+
-d '{"prompt": "hello"}'
59+
60+
# 通过查询参数指定端口,并附带其他业务查询参数
61+
curl "$ROCK_BASE_URL/sandboxes/sb-123/proxy/items?rock_target_port=8080&limit=10"
62+
```
63+
64+
---
65+
66+
## 2. WebSocket 代理
67+
68+
适用于需要 `ws://`(或 `wss://`)协议的服务 — 常见于流式输出、聊天、终端会话或任何全双工通道。
69+
70+
### 接入路径
71+
72+
```text
73+
ws(s)://$ROCK_BASE_URL/sandboxes/:sandbox_id/proxy/:path
74+
```
75+
76+
- 原始的 WebSocket 握手信息(subprotocol、自定义 header)会被透传。
77+
- 文本帧和二进制帧在双向之间透明转发。
78+
- 任意一端关闭连接,都会同步关闭对端的上游连接。
79+
80+
### 指定目标端口
81+
82+
与 HTTP 代理完全相同 — 支持路径、请求头、查询参数三种方式,同样**只能选其一**
83+
84+
| 优先级 | 指定方式 | 示例 |
85+
|--------|---------|------|
86+
| 1 | 路径前缀 | `/sandboxes/abc/proxy/port/9000/socket` |
87+
| 2 | 请求头 | `X-ROCK-Target-Port: 9000` |
88+
| 3 | 查询参数 | `?rock_target_port=9000` |
89+
90+
如果端口不合法(参见[端口限制](#3-端口限制)),WebSocket 会立刻以状态码 `1008`(策略违反)关闭。
91+
92+
### 使用示例
93+
94+
```bash
95+
# 使用 wscat
96+
wscat -c "$ROCK_WS_BASE/sandboxes/sb-123/proxy/port/9000/events"
97+
```
98+
99+
```javascript
100+
// 浏览器端
101+
const ws = new WebSocket(
102+
"wss://rock.example.com/sandboxes/sb-123/proxy/events?rock_target_port=9000"
103+
);
104+
ws.onmessage = (evt) => console.log(evt.data);
105+
ws.send("ping");
106+
```
107+
108+
---
109+
110+
## 3. 端口限制
111+
112+
WebSocket 代理对**沙箱内的目标端口**有以下限制:
113+
114+
| 规则 | 允许范围 / 值 |
115+
|------|--------------|
116+
| 最小端口 | `1024` |
117+
| 最大端口 | `65535` |
118+
| 禁用端口 | `22`(SSH) |
119+
120+
违反上述规则的请求会被拒绝:
121+
122+
- **HTTP 代理** → 返回 `400 Bad Request`,并在 `detail` 字段中说明原因。
123+
- **WebSocket 代理** → 连接以状态码 `1008` 关闭,并在 `reason` 中给出原因。
124+
125+
> `1024` 以下的端口为系统保留特权端口,因此被禁止;`22` 端口被禁止则是为了避免无意中暴露 SSH 服务。
126+
127+
---
128+
129+
## 4. 常见错误对照
130+
131+
| 现象 | 可能原因 |
132+
|------|---------|
133+
| `400 Bad Request: Cannot specify target port via multiple sources` | 同时使用了路径、请求头、查询参数中的两种以上方式指定端口 — 只保留其中一种。 |
134+
| `400 Bad Request` / WS `1008` 且提示端口范围错误 | 目标端口小于 `1024`、大于 `65535` 或等于 `22`|
135+
| WS 关闭码 `1011``Proxy error: ...`| 沙箱内的上游服务返回了错误,或无法被连通。请确认目标端口上确实有服务在监听。 |
136+
| 上游返回 `404 Not Found` | 沙箱内服务并不存在该 HTTP 路径 — 应检查目标服务的路由,而不是代理 URL。 |
137+
| 握手阶段连接卡住 | 沙箱可能仍在初始化。请先调用 `is_alive` 接口确认沙箱已就绪。 |
138+
139+
---
140+
141+
## 5. 快速选型
142+
143+
```text
144+
要调用沙箱内的 REST API? → HTTP 代理
145+
要连接沙箱内的 WebSocket 服务? → WebSocket 代理
146+
```
147+
148+
## 相关文档
149+
150+
- [API 参考](../References/api.md)
151+
- [配置指南](configuration.md)
152+
- [快速开始](../Getting%20Started/quickstart.md)
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
---
2+
sidebar_position: 6
3+
---
4+
5+
# Sandbox Proxy
6+
7+
ROCK Admin exposes a proxy layer that lets you reach services running **inside** a sandbox from **outside** the cluster, without giving each sandbox its own public address. The proxy supports two transport modes:
8+
9+
| Mode | Endpoint | Use it for |
10+
|------|----------|------------|
11+
| HTTP Proxy | `/sandboxes/:sandbox_id/proxy/...` | REST APIs, web UIs, file downloads, any HTTP/1.1 traffic |
12+
| WebSocket Proxy | `ws(s)://.../sandboxes/:sandbox_id/proxy/...` | Real-time channels, streaming, browser-based WS clients |
13+
14+
Both modes route by `sandbox_id`. The sandbox does **not** need a public IP — Admin terminates the client connection and forwards it to the right runtime inside the cluster.
15+
16+
---
17+
18+
## 1. HTTP Proxy
19+
20+
Forward any HTTP request to a service inside the sandbox.
21+
22+
### Endpoint
23+
24+
```text
25+
Methods : GET | POST | PUT | DELETE | PATCH | HEAD | OPTIONS
26+
URL : $ROCK_BASE_URL/sandboxes/:sandbox_id/proxy[/:path]
27+
```
28+
29+
- Method, headers, query string, and body are forwarded as-is to the target service.
30+
- The response (status code, headers, body) is streamed back to the client.
31+
32+
### Choosing the target port
33+
34+
The proxy needs to know which port inside the sandbox to hit. You can specify it in one of three ways — **pick exactly one**; mixing them returns `400 Bad Request`.
35+
36+
| Priority | Mechanism | Example |
37+
|----------|-----------|---------|
38+
| 1 | **Path prefix** | `/sandboxes/abc/proxy/port/8080/api/users` |
39+
| 2 | **Request header** | `X-ROCK-Target-Port: 8080` |
40+
| 3 | **Query parameter** | `?rock_target_port=8080` |
41+
42+
If no port is specified, the request is delivered to the sandbox's default service port.
43+
44+
### Examples
45+
46+
```bash
47+
# REST call via path-style port
48+
curl -X POST \
49+
"$ROCK_BASE_URL/sandboxes/sb-123/proxy/port/8080/v1/predict" \
50+
-H "Content-Type: application/json" \
51+
-d '{"prompt": "hello"}'
52+
53+
# Same call via header-style port
54+
curl -X POST \
55+
"$ROCK_BASE_URL/sandboxes/sb-123/proxy/v1/predict" \
56+
-H "X-ROCK-Target-Port: 8080" \
57+
-H "Content-Type: application/json" \
58+
-d '{"prompt": "hello"}'
59+
60+
# Query-string port + extra query params
61+
curl "$ROCK_BASE_URL/sandboxes/sb-123/proxy/items?rock_target_port=8080&limit=10"
62+
```
63+
64+
---
65+
66+
## 2. WebSocket Proxy
67+
68+
For services that expect a `ws://` (or `wss://`) connection — typical for streaming, chat, terminal sessions, or any full-duplex channel.
69+
70+
### Endpoint
71+
72+
```text
73+
ws(s)://$ROCK_BASE_URL/sandboxes/:sandbox_id/proxy/:path
74+
```
75+
76+
- The original WebSocket handshake (subprotocols, custom headers) is forwarded.
77+
- Both text and binary frames pass through transparently in both directions.
78+
- Closing either side cleanly tears down the upstream connection.
79+
80+
### Choosing the target port
81+
82+
Identical to HTTP Proxy — path, header, or query parameter — and again, only one at a time:
83+
84+
| Priority | Mechanism | Example |
85+
|----------|-----------|---------|
86+
| 1 | Path prefix | `/sandboxes/abc/proxy/port/9000/socket` |
87+
| 2 | Header | `X-ROCK-Target-Port: 9000` |
88+
| 3 | Query | `?rock_target_port=9000` |
89+
90+
Invalid port values (see [Port restrictions](#3-port-restrictions)) cause the WebSocket to close immediately with code `1008` (Policy Violation).
91+
92+
### Example
93+
94+
```bash
95+
# Using wscat
96+
wscat -c "$ROCK_WS_BASE/sandboxes/sb-123/proxy/port/9000/events"
97+
```
98+
99+
```javascript
100+
// Browser client
101+
const ws = new WebSocket(
102+
"wss://rock.example.com/sandboxes/sb-123/proxy/events?rock_target_port=9000"
103+
);
104+
ws.onmessage = (evt) => console.log(evt.data);
105+
ws.send("ping");
106+
```
107+
108+
---
109+
110+
## 3. Port restrictions
111+
112+
The WebSocket proxy enforces the following rules on the **target port** inside the sandbox:
113+
114+
| Rule | Allowed range / value |
115+
|------|----------------------|
116+
| Minimum port | `1024` |
117+
| Maximum port | `65535` |
118+
| Forbidden | `22` (SSH) |
119+
120+
Requests violating these rules are rejected:
121+
122+
- **HTTP Proxy**`400 Bad Request` with a `detail` message.
123+
- **WebSocket Proxy** → connection closed with code `1008` and a reason string.
124+
125+
> Ports below `1024` are blocked because they are reserved for privileged services; port `22` is blocked to prevent inadvertently exposing SSH.
126+
127+
---
128+
129+
## 4. Error handling reference
130+
131+
| Symptom | Likely cause |
132+
|---------|--------------|
133+
| `400 Bad Request: Cannot specify target port via multiple sources` | You set the port in two of path, header or query — pick one. |
134+
| `400 Bad Request` / WS close `1008` with port-range message | Target port is `< 1024`, `> 65535`, or equal to `22`. |
135+
| WS close `1011` (`Proxy error: ...`) | Upstream service inside the sandbox returned an error or could not be reached. Check that the service is actually listening on the target port. |
136+
| `404 Not Found` from the upstream | The HTTP path inside the sandbox does not exist — verify the service's route, not the proxy URL. |
137+
| Connection hangs on handshake | The sandbox may still be initializing. Confirm `is_alive` returns `True` before proxying. |
138+
139+
---
140+
141+
## 5. Quick decision guide
142+
143+
```text
144+
Need to call a REST API inside the sandbox? → HTTP Proxy
145+
Need a bidirectional WebSocket to a WS server? → WebSocket Proxy
146+
```
147+
148+
## Related documents
149+
150+
- [API Reference](../References/api.md)
151+
- [Configuration](configuration.md)
152+
- [Quick Start](../Getting%20Started/quickstart.md)

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)