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); + }); +});