From d38f2c437d06861e3151cb1e53fedfa02ad180f0 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Thu, 29 Apr 2021 15:10:25 -0400 Subject: [PATCH] Handle 503 responses from the status API (#98738) * Handle 503 responses from the status API * PR feedback: additional test --- .../core_app/status/lib/load_status.test.ts | 45 +++++++++++++++++++ .../public/core_app/status/lib/load_status.ts | 37 +++++++++------ 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/core/public/core_app/status/lib/load_status.test.ts b/src/core/public/core_app/status/lib/load_status.test.ts index e15c0e81f3d20..349f20a2385c6 100644 --- a/src/core/public/core_app/status/lib/load_status.test.ts +++ b/src/core/public/core_app/status/lib/load_status.test.ts @@ -100,6 +100,51 @@ describe('response processing', () => { expect(data.name).toEqual('My computer'); }); + test('throws when an error occurs', async () => { + http.get.mockReset(); + + http.get.mockRejectedValue(new Error()); + + await expect(loadStatus({ http, notifications })).rejects.toThrowError(); + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + }); + + test('throws when a 503 occurs which does not contain an appropriate payload', async () => { + const error = new Error() as any; + error.response = { status: 503 }; + error.body = {}; + + http.get.mockReset(); + http.get.mockRejectedValue(error); + + await expect(loadStatus({ http, notifications })).rejects.toThrowError(); + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + }); + + test('does not throw when a 503 occurs which contains an appropriate payload', async () => { + const error = new Error() as any; + error.response = { status: 503 }; + error.body = mockedResponse; + + http.get.mockReset(); + http.get.mockRejectedValue(error); + + const data = await loadStatus({ http, notifications }); + expect(data.name).toEqual('My computer'); + }); + + test('throws when a non-503 occurs which contains an appropriate payload', async () => { + const error = new Error() as any; + error.response = { status: 500 }; + error.body = mockedResponse; + + http.get.mockReset(); + http.get.mockRejectedValue(error); + + await expect(loadStatus({ http, notifications })).rejects.toThrowError(); + expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(1); + }); + test('includes the plugin statuses', async () => { const data = await loadStatus({ http, notifications }); expect(data.statuses).toEqual([ diff --git a/src/core/public/core_app/status/lib/load_status.ts b/src/core/public/core_app/status/lib/load_status.ts index 3c31da4c5397f..0748c3dfe1dec 100644 --- a/src/core/public/core_app/status/lib/load_status.ts +++ b/src/core/public/core_app/status/lib/load_status.ts @@ -113,21 +113,32 @@ export async function loadStatus({ try { response = await http.get('/api/status'); } catch (e) { - if ((e.response?.status ?? 0) >= 400) { - notifications.toasts.addDanger( - i18n.translate('core.statusPage.loadStatus.serverStatusCodeErrorMessage', { - defaultMessage: 'Failed to request server status with status code {responseStatus}', - values: { responseStatus: e.response?.status }, - }) - ); + // API returns a 503 response if not all services are available. + // In this case, we want to treat this as a successful API call, so that we can + // display Kibana's status correctly. + // 503 responses can happen for other reasons (such as proxies), so we make an educated + // guess here to determine if the response payload looks like an appropriate `StatusResponse`. + const ignoreError = e.response?.status === 503 && typeof e.body?.name === 'string'; + + if (ignoreError) { + response = e.body; } else { - notifications.toasts.addDanger( - i18n.translate('core.statusPage.loadStatus.serverIsDownErrorMessage', { - defaultMessage: 'Failed to request server status. Perhaps your server is down?', - }) - ); + if ((e.response?.status ?? 0) >= 400) { + notifications.toasts.addDanger( + i18n.translate('core.statusPage.loadStatus.serverStatusCodeErrorMessage', { + defaultMessage: 'Failed to request server status with status code {responseStatus}', + values: { responseStatus: e.response?.status }, + }) + ); + } else { + notifications.toasts.addDanger( + i18n.translate('core.statusPage.loadStatus.serverIsDownErrorMessage', { + defaultMessage: 'Failed to request server status. Perhaps your server is down?', + }) + ); + } + throw e; } - throw e; } return {