fix(framework): decodeFrame 改单层(服务器协议非双层)

真机联调发现:服务器实发单层 {app,route,rpc,data};旧客户端的'外层 data'是浏览器
MessageEvent(00_minhttp.js:266 ws.onmessage=config.onmessage),非协议层。框架传输层
已取 ev.data,decodeFrame 不应再剥一层。修正后 kick_server 等业务包能正确解析。
- decodeFrame 单层化 + 测试改单层帧
- 更正 docs/protocol/01 §3.2(双层→单层,附 MessageEvent 依据)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 20:25:36 +08:00
co-authored by Claude Opus 4.8
parent 5132fddc4e
commit 96c6c7c914
5 changed files with 65 additions and 63 deletions
@@ -7,29 +7,34 @@ test('encodeOutbound 产出单层信封字符串', () => {
assert.deepEqual(JSON.parse(s), { app: 'youle', route: 'agent', rpc: 'player_login', data: { openid: 'o' } });
});
// 服务器协议为单层:frame 即服务器实发帧(传输层已取 MessageEvent.data)。
test('decodeFrame:握手包 @toconcon 识别为 handshake', () => {
const frame = JSON.stringify({ data: '@toconconXYZ...' });
assert.deepEqual(decodeFrame(frame), { kind: 'handshake' });
assert.deepEqual(decodeFrame('@toconconXYZ...'), { kind: 'handshake' });
});
test('decodeFrame:心跳包 @serverheartbeat 识别为 heartbeat', () => {
const frame = JSON.stringify({ data: JSON.stringify({ com: '@serverheartbeat' }) });
const frame = JSON.stringify({ com: '@serverheartbeat' });
assert.deepEqual(decodeFrame(frame), { kind: 'heartbeat' });
});
test('decodeFrame:特殊错误包 webserve-服务器未工作', () => {
const frame = JSON.stringify({ data: 'webserve-服务器未工作' });
assert.deepEqual(decodeFrame(frame), { kind: 'serverDown' });
assert.deepEqual(decodeFrame('webserve-服务器未工作'), { kind: 'serverDown' });
});
test('decodeFrame:正常业务包解出内层 {route,rpc,data}', () => {
test('decodeFrame:正常业务包(单层)解出 {route,rpc,data}', () => {
const inner = { route: 'agent', rpc: 'player_login', data: { state: 0, playerid: 9 } };
const frame = JSON.stringify({ data: JSON.stringify(inner) });
assert.deepEqual(decodeFrame(frame), { kind: 'message', message: inner });
assert.deepEqual(decodeFrame(JSON.stringify(inner)), { kind: 'message', message: inner });
});
test('decodeFrame:内层为对象(非字符串)也能解', () => {
const inner = { route: 'room', rpc: 'other_join_room', data: { seat: 1 } };
const frame = JSON.stringify({ data: inner });
assert.deepEqual(decodeFrame(frame), { kind: 'message', message: inner });
test('decodeFrame:带 app 字段的单层业务包(服务器实测格式)', () => {
const frame = JSON.stringify({ app: 'youle', route: 'agent', rpc: 'kick_server', data: { msg: '检查到新版本' } });
const r = decodeFrame(frame);
assert.equal(r.kind, 'message');
assert.equal(r.kind === 'message' && r.message.rpc, 'kick_server');
});
test('decodeFrame:无法解析的帧安全忽略', () => {
assert.deepEqual(decodeFrame('not json'), { kind: 'ignore' });
assert.deepEqual(decodeFrame(JSON.stringify({ foo: 1 })), { kind: 'ignore' });
});