From b65550fbbad0810a6e678961e7d27fe8214e7cdd Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 22 Jul 2025 08:39:39 +0300 Subject: [PATCH 1/3] Fix different error code in status badge --- .../use_send_current_request/send_request.ts | 17 ++- .../status_code_extraction.test.ts | 111 ++++++++++++++++++ 2 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts diff --git a/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/send_request.ts b/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/send_request.ts index 5cc5c51e65b60..5f9fc676f71b2 100644 --- a/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/send_request.ts +++ b/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/send_request.ts @@ -50,10 +50,21 @@ const extractStatusCodeAndText = (response: Response | undefined, path: string) // For ES requests, we need to extract the status code and text from the response // headers, due to the way the proxy set up to avoid mirroring the status code which could be 401 // and trigger a login prompt. See for more details: https://github.com/elastic/kibana/issues/140536 - const statusCode = parseInt(response?.headers.get('x-console-proxy-status-code') ?? '500', 10); - const statusText = response?.headers.get('x-console-proxy-status-text') ?? 'error'; + const proxyStatusCode = response?.headers.get('x-console-proxy-status-code'); + const proxyStatusText = response?.headers.get('x-console-proxy-status-text'); - return { statusCode, statusText }; + // If proxy headers are missing (e.g., validation errors), use the actual response status + if (!proxyStatusCode) { + return { + statusCode: parseInt(String(response?.status ?? 500), 10), + statusText: response?.statusText ?? 'error', + }; + } + + return { + statusCode: parseInt(proxyStatusCode, 10), + statusText: proxyStatusText ?? 'error', + }; }; let CURRENT_REQ_ID = 0; diff --git a/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts b/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts new file mode 100644 index 0000000000000..d537a425d635a --- /dev/null +++ b/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { HttpSetup } from '@kbn/core/public'; + +jest.unmock('./send_request'); + +describe('Status Code Extraction in sendRequest', () => { + let mockHttp: jest.Mocked; + + beforeEach(() => { + mockHttp = { + post: jest.fn(), + } as any; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('extractStatusCodeAndText function behavior', () => { + it('should use proxy headers when available for ES requests', async () => { + const { sendRequest } = await import('./send_request'); + + const mockResponse = { + response: { + status: 200, // Actual HTTP status + statusText: 'OK', + headers: new Map([ + ['x-console-proxy-status-code', '404'], // ES status from proxy + ['x-console-proxy-status-text', 'Not Found'], + ['Content-Type', 'application/json'], + ]), + }, + body: JSON.stringify({ error: 'index_not_found_exception' }), + }; + + mockHttp.post.mockResolvedValue(mockResponse); + + const result = await sendRequest({ + http: mockHttp, + requests: [{ url: '/_search', method: 'GET', data: ['{}'] }], + }); + + expect(result[0].response.statusCode).toBe(404); // Should use proxy header + expect(result[0].response.statusText).toBe('Not Found'); + }); + + it('should fall back to actual response status when proxy headers are missing', async () => { + const { sendRequest } = await import('./send_request'); + + const mockResponse = { + response: { + status: 400, + statusText: 'Bad Request', + headers: new Map([ + ['Content-Type', 'application/json'], + ]), + }, + body: JSON.stringify({ + statusCode: 400, + error: 'Bad Request', + message: + "Method must be one of, case insensitive ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']. Received 'INVALIDMETHOD'.", + }), + }; + + mockHttp.post.mockResolvedValue(mockResponse); + + const result = await sendRequest({ + http: mockHttp, + requests: [{ url: '/_search', method: 'INVALIDMETHOD', data: ['{}'] }], + }); + + expect(result[0].response.statusCode).toBe(400); // Should use actual response status, not 500 + expect(result[0].response.statusText).toBe('Bad Request'); + }); + + it('should handle empty proxy header as missing header', async () => { + const { sendRequest } = await import('./send_request'); + + const mockResponse = { + response: { + status: 400, + statusText: 'Bad Request', + headers: new Map([ + ['x-console-proxy-status-code', ''], // Empty header value + ['Content-Type', 'application/json'], + ]), + }, + body: JSON.stringify({ error: 'validation error' }), + }; + + mockHttp.post.mockResolvedValue(mockResponse); + + const result = await sendRequest({ + http: mockHttp, + requests: [{ url: '/_search', method: 'INVALID', data: ['{}'] }], + }); + + expect(result[0].response.statusCode).toBe(400); // Should fall back to actual status + expect(result[0].response.statusText).toBe('Bad Request'); + }); + }); +}); From 00e36a80d6cb6c135623d90505bd1ba73aa3f7e3 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 22 Jul 2025 08:39:46 +0300 Subject: [PATCH 2/3] commit with @elastic email From 7953bf81aec46d4543a226e059bb0b327d80f4ec Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 22 Jul 2025 06:12:23 +0000 Subject: [PATCH 3/3] [CI] Auto-commit changed files from 'node scripts/eslint_all_files --no-cache --fix' --- .../use_send_current_request/status_code_extraction.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts b/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts index d537a425d635a..f34a9d072099e 100644 --- a/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts +++ b/src/platform/plugins/shared/console/public/application/hooks/use_send_current_request/status_code_extraction.test.ts @@ -59,9 +59,7 @@ describe('Status Code Extraction in sendRequest', () => { response: { status: 400, statusText: 'Bad Request', - headers: new Map([ - ['Content-Type', 'application/json'], - ]), + headers: new Map([['Content-Type', 'application/json']]), }, body: JSON.stringify({ statusCode: 400,