diff --git a/src/api/feedbackHandlers.ts b/src/api/feedbackHandlers.ts index 3ac12780..e87ed8a0 100644 --- a/src/api/feedbackHandlers.ts +++ b/src/api/feedbackHandlers.ts @@ -9,7 +9,9 @@ async function readJsonBody(c: ApiContext): Promise> { if (c.req.method !== 'POST') { return {}; } - return c.req.json>().catch(() => ({})); + const body = await c.req.json().catch(() => ({})); + // JSON 본문이 null 등 객체가 아니면 빈 요청으로 처리합니다. + return typeof body === 'object' && body !== null ? (body as Record) : {}; } function queryInput(c: ApiContext): Partial { diff --git a/tests/app/app-api-feedback.test.ts b/tests/app/app-api-feedback.test.ts index dd38ef28..63f21c29 100644 --- a/tests/app/app-api-feedback.test.ts +++ b/tests/app/app-api-feedback.test.ts @@ -133,6 +133,18 @@ describe('/api/feedback/requests', () => { expect(data.error.code).toBe('MISSING_FEEDBACK_TITLE'); }); + it('null JSON 본문은 빈 요청으로 처리해 필수값 오류를 반환한다', async () => { + const res = await app.request('/api/feedback/requests', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: 'null', + }); + + expect(res.status).toBe(400); + const data = await res.json(); + expect(data.error.code).toBe('MISSING_FEEDBACK_TITLE'); + }); + it('Supabase 저장 실패를 500으로 반환한다', async () => { mockFetch.mockRejectedValue('raw failure');