Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ Authentication is enforced only when `server.api_key` is set. If the value is em
All API endpoints (except `/health`, `/docs`, `/redoc`) require authentication via the `OPEN-SANDBOX-API-KEY` header when authentication is enabled:

```bash
curl http://localhost:8080/sandboxes
curl http://localhost:8080/v1/sandboxes
```

### Example usage

**Create a Sandbox**

```bash
curl -X POST "http://localhost:8080/sandboxes" \
curl -X POST "http://localhost:8080/v1/sandboxes" \
-H "OPEN-SANDBOX-API-KEY: your-secret-api-key" \
-H "Content-Type: application/json" \
-d '{
Expand Down Expand Up @@ -209,18 +209,18 @@ Response:

```bash
curl -H "OPEN-SANDBOX-API-KEY: your-secret-api-key" \
http://localhost:8080/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab
http://localhost:8080/v1/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab
```

**Get Service Endpoint**

```bash
curl -H "OPEN-SANDBOX-API-KEY: your-secret-api-key" \
http://localhost:8080/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab/endpoints/8000
http://localhost:8080/v1/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab/endpoints/8000

# execd (agent) endpoint
curl -H "OPEN-SANDBOX-API-KEY: your-secret-api-key" \
http://localhost:8080/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab/endpoints/44772
http://localhost:8080/v1/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab/endpoints/44772
```

Response:
Expand All @@ -233,7 +233,7 @@ Response:
**Renew Expiration**

```bash
curl -X POST "http://localhost:8080/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab/renew-expiration" \
curl -X POST "http://localhost:8080/v1/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab/renew-expiration" \
-H "OPEN-SANDBOX-API-KEY: your-secret-api-key" \
-H "Content-Type: application/json" \
-d '{
Expand All @@ -246,7 +246,7 @@ curl -X POST "http://localhost:8080/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890
```bash
curl -X DELETE \
-H "OPEN-SANDBOX-API-KEY: your-secret-api-key" \
http://localhost:8080/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab
http://localhost:8080/v1/sandboxes/a1b2c3d4-5678-90ab-cdef-1234567890ab
```

## Architecture
Expand Down
14 changes: 7 additions & 7 deletions server/README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,15 @@ curl http://localhost:8080/health
当鉴权开启时,除 `/health`、`/docs`、`/redoc` 外的 API 端点均需要通过 `OPEN-SANDBOX-API-KEY` 请求头进行认证:

```bash
curl http://localhost:8080/sandboxes
curl http://localhost:8080/v1/sandboxes
```

### 使用示例

**创建沙箱**

```bash
curl -X POST "http://localhost:8080/sandboxes" \
curl -X POST "http://localhost:8080/v1/sandboxes" \
-H "Content-Type: application/json" \
-d '{
"image": {
Expand Down Expand Up @@ -210,17 +210,17 @@ curl -X POST "http://localhost:8080/sandboxes" \
**获取沙箱详情**

```bash
curl http://localhost:8080/sandboxes/<sandbox-id>
curl http://localhost:8080/v1/sandboxes/<sandbox-id>
```

**获取服务端点**

```bash
# 获取自定义服务端点
curl http://localhost:8080/sandboxes/<sandbox-id>/endpoints/8000
curl http://localhost:8080/v1/sandboxes/<sandbox-id>/endpoints/8000

# 获取OpenSandbox守护进程(execd)端点
curl http://localhost:8080/sandboxes/<sandbox-id>/endpoints/44772
curl http://localhost:8080/v1/sandboxes/<sandbox-id>/endpoints/44772
```

响应:
Expand All @@ -233,7 +233,7 @@ curl http://localhost:8080/sandboxes/<sandbox-id>/endpoints/44772
**续期沙箱**

```bash
curl -X POST "http://localhost:8080/sandboxes/<sandbox-id>/renew-expiration" \
curl -X POST "http://localhost:8080/v1/sandboxes/<sandbox-id>/renew-expiration" \
-H "Content-Type: application/json" \
-d '{
"expiresAt": "2024-01-15T12:30:00Z"
Expand All @@ -243,7 +243,7 @@ curl -X POST "http://localhost:8080/sandboxes/<sandbox-id>/renew-expiration" \
**删除沙箱**

```bash
curl -X DELETE http://localhost:8080/sandboxes/<sandbox-id>
curl -X DELETE http://localhost:8080/v1/sandboxes/<sandbox-id>
```

## 系统架构
Expand Down
3 changes: 2 additions & 1 deletion server/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@
# Add authentication middleware
app.add_middleware(AuthMiddleware, config=app_config)

# Include API routes at root
# Include API routes at root and versioned prefix
app.include_router(router)
app.include_router(router, prefix="/v1")

DEFAULT_ERROR_CODE = "GENERAL::UNKNOWN_ERROR"
DEFAULT_ERROR_MESSAGE = "An unexpected error occurred."
Expand Down
17 changes: 9 additions & 8 deletions server/tests/smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ error() {
}

BASE_URL="${BASE_URL:-http://localhost:32888}"
BASE_API_URL="${BASE_URL}/v1"
API_KEY_HEADER=()
if [[ -n "${OPEN_SANDBOX_API_KEY:-}" ]]; then
API_KEY_HEADER=(-H "OPEN-SANDBOX-API-KEY: ${OPEN_SANDBOX_API_KEY}")
Expand All @@ -68,7 +69,7 @@ wait_for_running() {
local deadline=$((SECONDS + 10))
while true; do
local resp
resp=$(curl_json "${BASE_URL}/sandboxes/${SANDBOX_ID}")
resp=$(curl_json "${BASE_API_URL}/sandboxes/${SANDBOX_ID}")
local state
state=$(python - <<'PY' "${resp}"
import json,sys
Expand Down Expand Up @@ -97,7 +98,7 @@ wait_for_expired() {
local deadline=$((SECONDS + 90))
while true; do
local resp body status
resp=$(curl_json_status "${BASE_URL}/sandboxes/${sandbox_id}")
resp=$(curl_json_status "${BASE_API_URL}/sandboxes/${sandbox_id}")
status="${resp##*$'\n'}"
body="${resp%$'\n'*}"
if [[ "${status}" == "404" ]]; then
Expand Down Expand Up @@ -128,7 +129,7 @@ step "Create sandbox (60s TTL)"
create_resp=$(curl_json \
-H 'Content-Type: application/json' \
-d "${create_payload}" \
"${BASE_URL}/sandboxes")
"${BASE_API_URL}/sandboxes")

SANDBOX_ID=$(python - <<'PY' "${create_resp}"
import json,sys
Expand Down Expand Up @@ -166,7 +167,7 @@ list_resp=$(curl_json \
--data-urlencode "metadata=hello=world" \
--data-urlencode "page=1" \
--data-urlencode "pageSize=10" \
"${BASE_URL}/sandboxes")
"${BASE_API_URL}/sandboxes")

python - <<'PY' "${list_resp}" "${SANDBOX_ID}"
import json,sys
Expand Down Expand Up @@ -196,7 +197,7 @@ renew_resp=$(curl_json \
-X POST \
-H 'Content-Type: application/json' \
-d "${renew_payload}" \
"${BASE_URL}/sandboxes/${SANDBOX_ID}/renew-expiration")
"${BASE_API_URL}/sandboxes/${SANDBOX_ID}/renew-expiration")
renewed=$(python - <<'PY' "${renew_resp}"
import json,sys
body=json.loads(sys.argv[1])
Expand All @@ -206,7 +207,7 @@ PY
echo "Expiration renewed to: ${renewed}"

step "Request endpoint on port 8080"
endpoint_resp=$(curl_json "${BASE_URL}/sandboxes/${SANDBOX_ID}/endpoints/8080")
endpoint_resp=$(curl_json "${BASE_API_URL}/sandboxes/${SANDBOX_ID}/endpoints/8080")
endpoint=$(python - <<'PY' "${endpoint_resp}"
import json,sys
body=json.loads(sys.argv[1])
Expand All @@ -216,7 +217,7 @@ PY
echo "Endpoint: ${endpoint}"

step "Delete sandbox"
curl_json -X DELETE "${BASE_URL}/sandboxes/${SANDBOX_ID}"
curl_json -X DELETE "${BASE_API_URL}/sandboxes/${SANDBOX_ID}"
echo "Sandbox ${SANDBOX_ID} deleted."

step "Create short-lived sandbox (60s TTL) for auto-expiration"
Expand All @@ -232,7 +233,7 @@ create_payload_short='{
create_resp_short=$(curl_json \
-H 'Content-Type: application/json' \
-d "${create_payload_short}" \
"${BASE_URL}/sandboxes")
"${BASE_API_URL}/sandboxes")

SANDBOX_ID=$(python - <<'PY' "${create_resp_short}"
import json,sys
Expand Down
8 changes: 8 additions & 0 deletions server/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ def test_missing_api_key(self, client: TestClient):
assert response.status_code == 401
assert "MISSING_API_KEY" in response.json()["code"]

def test_missing_api_key_v1_prefix(self, client: TestClient):
"""
Test request without API key on versioned route returns 401.
"""
response = client.get("/v1/sandboxes/123e4567-e89b-12d3-a456-426614174000")
assert response.status_code == 401
assert "MISSING_API_KEY" in response.json()["code"]

def test_invalid_api_key(self, client: TestClient):
"""
Test request with invalid API key returns 401.
Expand Down
Loading