线上只托管静态文件、不暴露玩具级用户 API;HTTPS 域名下大厅隐藏登录。部署步骤与 Nginx 配置记在 docs/deploy.md,便于以后 rsync 更新。 Co-authored-by: Cursor <cursoragent@cursor.com>
95 lines
3.2 KiB
Markdown
95 lines
3.2 KiB
Markdown
# SoundGame Web 服务器(web/server/server.js)
|
||
|
||
Node 零依赖(仅用内置模块)的静态文件 + 用户系统 API 服务器。
|
||
|
||
## 启动
|
||
|
||
```bash
|
||
# 推荐:用项目自带 node
|
||
tools/node/bin/node web/server/server.js
|
||
|
||
# 或用封装脚本(打印局域网地址)
|
||
bash web/serve.sh
|
||
|
||
# 自定义端口(默认 8000)
|
||
PORT=8001 tools/node/bin/node web/server/server.js
|
||
```
|
||
|
||
- 静态根目录:`web/`(`/` 即游戏大厅 `index.html`)
|
||
- 数据目录:`web/server/data/`(首次启动自动创建)
|
||
|
||
## ⚠ 安全说明
|
||
|
||
这是**家庭局域网玩具级认证**,请勿暴露到公网:
|
||
|
||
- PIN 以**明文**存储在 `data/users.json`;
|
||
- token 永不过期,明文存于 `data/sessions.json`;
|
||
- HTTP 明文传输,无 TLS、无防爆破、无速率限制。
|
||
|
||
用途仅限于同一 WiFi 下的家庭成员各自存档。公网 `game.xiangsilian.com` **不跑本服务**,
|
||
只托管静态文件(见 `docs/deploy.md`)。要公网开用户系统请换正经认证方案。
|
||
|
||
## API
|
||
|
||
所有 API 请求/响应均为 JSON(`Content-Type: application/json`)。
|
||
错误响应统一为 `{ "error": "描述" }` + 相应 HTTP 状态码。
|
||
|
||
### POST /api/register
|
||
|
||
注册新用户。
|
||
|
||
- 请求:`{ "username": "ming", "pin": "1234" }`
|
||
- `username`:1~24 位字母/数字/中文/`_`/`-`
|
||
- `pin`:4~6 位数字
|
||
- 成功:`201 { "ok": true, "username": "ming" }`
|
||
- 失败:`400`(格式非法)/ `409 { "error": "用户名已被注册" }`
|
||
|
||
### POST /api/login
|
||
|
||
登录,返回 token。
|
||
|
||
- 请求:`{ "username": "ming", "pin": "1234" }`
|
||
- 成功:`200 { "ok": true, "token": "<48 位随机 hex>", "username": "ming" }`
|
||
- 失败:`401 { "error": "用户名或 PIN 错误" }`
|
||
|
||
token 存内存并落盘 `data/sessions.json`(服务器重启后会话仍有效)。
|
||
|
||
### GET /api/progress?game=xxx
|
||
|
||
读取某游戏的进度数据。
|
||
|
||
- 请求头:`Authorization: Bearer <token>`
|
||
- 成功:`200 { "game": "escape", "data": { ... } }`(无存档时 `data` 为 `null`)
|
||
- 失败:`401`(token 缺失/无效)/ `400`(缺少 game 参数)
|
||
|
||
### PUT /api/progress
|
||
|
||
写入某游戏的进度数据(覆盖该 game 键)。
|
||
|
||
- 请求头:`Authorization: Bearer <token>`
|
||
- 请求:`{ "game": "escape", "data": { "summary": "已逃脱 2 次 / 最快 3:25", ... } }`
|
||
- `game`:1~32 位字母/数字/`_`/`-`;大厅约定用 `_settings` 存用户设置
|
||
- `data`:任意 JSON 值;大厅卡片会展示 `data.summary` 字符串(若存在)
|
||
- 成功:`200 { "ok": true, "game": "escape" }`
|
||
- 失败:`401` / `400`
|
||
|
||
## 数据格式
|
||
|
||
```
|
||
web/server/data/
|
||
├── users.json { "<username>": "<pin>" }
|
||
├── sessions.json { "<token>": "<username>" }
|
||
└── <username>.json { "<game>": <data>, ... } 一用户一文件
|
||
```
|
||
|
||
所有写入按文件串行排队(Promise 链),tmp + rename 原子落盘,并发请求不会写坏文件。
|
||
|
||
## 静态服务
|
||
|
||
- MIME:`.ogg audio/ogg`、`.m4a audio/mp4`、`.js text/javascript`、
|
||
`.html text/html`、`.png image/png`、`.json application/json` 等;
|
||
- 目录自动解析 `index.html`;
|
||
- 支持简化版 HTTP Range(单段 `bytes=start-end` / `start-` / `-suffix`),
|
||
返回 206 + `Content-Range`,供音频元素拖动进度;
|
||
- 路径穿越防护:请求路径限制在 `web/` 内。
|