diff --git a/deploy/cloudflare/src/dns.ts b/deploy/cloudflare/src/dns.ts index 2e3f0ad..f4e2728 100644 --- a/deploy/cloudflare/src/dns.ts +++ b/deploy/cloudflare/src/dns.ts @@ -23,14 +23,25 @@ interface CfResult { result?: unknown; } +/** 空响应体视为 2xx 成功(CF 部分 API 返回 200/204 无 body),JSON 解析失败则按状态码判断。 */ +async function toResult(res: Response): Promise { + const text = await res.text(); + if (!text.trim()) return { success: res.ok }; + try { + return (JSON.parse(text)) as CfResult; + } catch { + return { success: res.ok, errors: [{ code: 0, message: `非 JSON 响应:${text.slice(0, 80)}` }] }; + } +} + async function cfGet(url: string, token: string): Promise { const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }); - return (await res.json()) as CfResult; + return toResult(res); } async function cfDelete(url: string, token: string): Promise { const res = await fetch(url, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` } }); - return (await res.json()) as CfResult; + return toResult(res); } async function cfPost(url: string, token: string, body: unknown): Promise { diff --git a/deploy/cloudflare/test/dns.test.ts b/deploy/cloudflare/test/dns.test.ts index faf431f..32dac55 100644 --- a/deploy/cloudflare/test/dns.test.ts +++ b/deploy/cloudflare/test/dns.test.ts @@ -94,6 +94,32 @@ describe('removeLegacyCustomDomains(B 方案迁移:解绑同域遗留 Custom await removeLegacyCustomDomains({ accountId: 'acc-1', domain: 'demo.handywote.top', apiToken: 'tok' }); expect(calls.some((c) => c.method === 'DELETE')).toBe(false); }); + + it('DELETE 返回空 body(真机:200 无体)→ 仍计成功并记录日志', async () => { + // stubCf 只能回放 JSON——这里直接手工 stub 空体响应 + const rawFetch = vi.fn(async (input: string | URL | Request, init?: RequestInit) => { + const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url; + if (url.endsWith('/workers/domains')) { + return new Response(JSON.stringify({ + success: true, + result: [{ id: 'd1', hostname: 'demo.handywote.top' }], + }), { status: 200 }); + } + if (init?.method === 'DELETE') { + return new Response(null, { status: 200 }); // 空体 + } + return new Response('{}', { status: 200 }); + }); + vi.stubGlobal('fetch', rawFetch); + const logs: string[] = []; + await removeLegacyCustomDomains({ + accountId: 'acc-1', + domain: 'demo.handywote.top', + apiToken: 'tok', + log: (m) => logs.push(m), + }); + expect(logs.filter((l) => l.includes('已解绑'))).toHaveLength(1); + }); }); describe('ensureZoneRecord(幂等 DNS 自愈)', () => {