From f56bbe76d70bcd0ee267cd2640135fbd2fd93bd6 Mon Sep 17 00:00:00 2001 From: xcbyy <2578898740@qq.com> Date: Wed, 21 Oct 2026 10:52:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(api):=20=E6=94=B6=E8=97=8F=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=8E=A5=E5=8F=A3=E4=B8=8D=E5=86=8D=E6=8A=8A=20401=20?= =?UTF-8?q?=E5=90=9E=E6=88=90=20500?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /api/favorites/check 的 catch 改为透传 err.status/err.code(未登录返回 401 + 40010/40100,而非 500) - 线上日志确认根因:未携带用户 token 时 resolveSecureUserId 抛 401 被包装成 500 - 新增 favorites-status-code.spec.ts(105 套件/703 用例全绿);冒烟 3/3 --- server/src/index.ts | 5 +++- server/tests/favorites-status-code.spec.ts | 28 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 server/tests/favorites-status-code.spec.ts diff --git a/server/src/index.ts b/server/src/index.ts index c052ec7..d853dc6 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -4823,7 +4823,10 @@ app.get('/api/favorites/check', async (req: Request, res: Response) => { data: { isFavorite: isFav } }); } catch (err: any) { - res.status(500).json({ code: 50000, message: err.message }); + // 保留 401/403 语义(未登录/越权),不要把鉴权失败吞成 500 + const statusCode = err.status || 500; + const errCode = err.code || 50000; + res.status(statusCode).json({ code: errCode, message: err.message }); } }); diff --git a/server/tests/favorites-status-code.spec.ts b/server/tests/favorites-status-code.spec.ts new file mode 100644 index 0000000..5f4a19d --- /dev/null +++ b/server/tests/favorites-status-code.spec.ts @@ -0,0 +1,28 @@ +// 已读取AGENTS.md +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * 第八十九批:收藏状态接口不得把 401 吞成 500。 + * 背景:secure-by-default 后未登录请求 resolveSecureUserId 抛 401, + * 原路由 catch 硬编码 res.status(500),导致前端只看到"系统错误"而不是"请先登录"。 + */ +describe('第八十九批收藏状态接口状态码闸门', () => { + const root = path.resolve(__dirname, '../../'); + const indexCode = fs.readFileSync(path.join(root, 'server/src/index.ts'), 'utf-8'); + const repoCode = fs.readFileSync(path.join(root, 'server/src/db/repository.ts'), 'utf-8'); + + it('favorites/check 透传 err.status(401/403 不再变 500)', () => { + const start = indexCode.indexOf("app.get('/api/favorites/check'"); + expect(start).toBeGreaterThan(-1); + const block = indexCode.slice(start, start + 900); + expect(block).toContain('const statusCode = err.status || 500'); + expect(block).toContain('res.status(statusCode)'); + expect(block).not.toContain('res.status(500).json'); + }); + + it('仓储提供 isFavorite 且仅定义一次', () => { + const matches = repoCode.match(/async isFavorite\(/g) || []; + expect(matches.length).toBe(1); + }); +});