From db405d243c1f0913c9bfa698a24fc076e7ede933 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 2 Feb 2026 17:51:27 -0500 Subject: [PATCH] [Cases][Webhook] - Better handle 204 responses (#251090) ## Summary Currently when an update is made to an external connector that returns a `204` no content response, the rest of the incident update fails. This should not occur as a 204 is a valid response Fixes https://github.com/elastic/kibana/issues/251108 ### Checklist Check the PR satisfies following conditions. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios (cherry picked from commit 926e3a2ea37ef37f0a2faed96c241a8179901a24) --- .../cases_webhook/service.test.ts | 42 +++++++++++++++++++ .../cases_webhook/utils.test.ts | 26 ++++++++++++ .../connector_types/cases_webhook/utils.ts | 5 +++ 3 files changed, 73 insertions(+) diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/service.test.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/service.test.ts index b3cc82a68554e..bbf48a457b645 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/service.test.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/service.test.ts @@ -1354,6 +1354,48 @@ describe('Cases webhook service', () => { '[Action][Webhook - Case Management]: Unable to update case with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' ); }); + + it('it should throw if the request status is a 204 and has data', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ + data: 'some data', + headers: { ['content-type']: 'text/html' }, + status: 204, + }) + ); + + await expect(service.updateIncident(incident)).rejects.toThrow( + '[Action][Webhook - Case Management]: Unable to update case with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' + ); + }); + + it('it should NOT throw if the request status is a 204 and is empty', async () => { + // Initial mock for the update call + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: undefined, + headers: { ['content-type']: 'text/html' }, + status: 204, + }) + ); + + // Second mock for the getIncident call inside updateIncident + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + }, + }) + ); + + await expect(service.updateIncident(incident)).resolves.toEqual({ + id: '1', + title: 'CK-1', + pushedDate: mockTime.toISOString(), + url: 'https://coolsite.net/browse/CK-1', + }); + }); }); describe('createComment', () => { diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.test.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.test.ts index 8e73e1d6682fd..a069e11869fb4 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.test.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.test.ts @@ -64,6 +64,32 @@ describe('cases_webhook/utils', () => { headers: new AxiosHeaders({}), }, }; + + it('Does not throw when the response status is 204 and there is no data', () => { + expect(() => + throwDescriptiveErrorIfResponseIsNotValid({ + res: { + ...res, + status: 204, + data: undefined, + }, + }) + ).not.toThrow(); + }); + + it('Throws when the response status is 204 and requiredAttributesToBeInTheResponse is set', () => { + expect(() => + throwDescriptiveErrorIfResponseIsNotValid({ + res: { + ...res, + status: 204, + data: undefined, + }, + requiredAttributesToBeInTheResponse: ['field.simple'], + }) + ).toThrow(); + }); + it('Throws error when missing content-type', () => { expect(() => throwDescriptiveErrorIfResponseIsNotValid({ diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.ts index 2a13e35a375a9..753915de24833 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/cases_webhook/utils.ts @@ -43,6 +43,11 @@ export const throwDescriptiveErrorIfResponseIsNotValid = ({ const contentType = res.headers['content-type']; const data = res.data; + // If status is 204 and there is no data, we just return + if (res.status === 204 && isEmpty(data) && requiredAttributesToBeInTheResponse.length === 0) { + return; + } + /** * Check that the content-type of the response is application/json. * Then includes is added because the header can be application/json;charset=UTF-8.