From 84b7efb393a8320c335a545e2a89f7ab0c8bda4c Mon Sep 17 00:00:00 2001 From: Levente Balogh Date: Thu, 26 May 2022 13:01:53 +0200 Subject: [PATCH] fix: only "swallow" the json() parsing error if the response is empty (#47493) --- public/app/core/utils/fetch.test.ts | 25 ++++++++++++++++++++++++- public/app/core/utils/fetch.ts | 10 ++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/public/app/core/utils/fetch.test.ts b/public/app/core/utils/fetch.test.ts index 9d46e039aa3..b510ea90bf4 100644 --- a/public/app/core/utils/fetch.test.ts +++ b/public/app/core/utils/fetch.test.ts @@ -135,7 +135,12 @@ describe('parseCredentials', () => { }); describe('parseResponseBody', () => { - const rsp = {} as unknown as Response; + let rsp: Response; + + beforeEach(() => { + rsp = new Response(); + }); + it('parses json', async () => { const value = { hello: 'world' }; const body = await parseResponseBody( @@ -148,6 +153,24 @@ describe('parseResponseBody', () => { expect(body).toEqual(value); }); + it('returns an empty object {} when the response is empty but is declared as JSON type', async () => { + rsp.headers.set('Content-Length', '0'); + jest.spyOn(console, 'warn').mockImplementation(); + + const json = jest.fn(); + const body = await parseResponseBody( + { + ...rsp, + json, + }, + 'json' + ); + + expect(body).toEqual({}); + expect(json).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledTimes(1); + }); + it('parses text', async () => { const value = 'RAW TEXT'; const body = await parseResponseBody( diff --git a/public/app/core/utils/fetch.ts b/public/app/core/utils/fetch.ts index c4b00d2034e..c057dda9111 100644 --- a/public/app/core/utils/fetch.ts +++ b/public/app/core/utils/fetch.ts @@ -106,13 +106,15 @@ export async function parseResponseBody( return response.blob() as any; case 'json': - try { - return await response.json(); - } catch (err) { - console.warn(`${response.url} returned an invalid JSON -`, err); + // An empty string is not a valid JSON. + // Sometimes (unfortunately) our APIs declare their Content-Type as JSON, however they return an empty body. + if (response.headers.get('Content-Length') === '0') { + console.warn(`${response.url} returned an invalid JSON`); return {} as unknown as T; } + return await response.json(); + case 'text': return response.text() as any; }