diff --git a/webserver/webserver/src/main/java/io/helidon/webserver/http/ErrorHandlers.java b/webserver/webserver/src/main/java/io/helidon/webserver/http/ErrorHandlers.java index de1d33b9288..6366ded8381 100644 --- a/webserver/webserver/src/main/java/io/helidon/webserver/http/ErrorHandlers.java +++ b/webserver/webserver/src/main/java/io/helidon/webserver/http/ErrorHandlers.java @@ -212,7 +212,7 @@ private void handleError(ConnectionContext ctx, if (!response.reset()) { ctx.log(LOGGER, System.Logger.Level.WARNING, "Unable to reset response for error handler."); throw new CloseConnectionException( - "Cannot send response of a simple handler, status and headers already written"); + "Cannot send response of a simple handler, status and headers already written", e); } try { it.handle(request, response, e); diff --git a/webserver/webserver/src/test/java/io/helidon/webserver/http/ErrorHandlersTest.java b/webserver/webserver/src/test/java/io/helidon/webserver/http/ErrorHandlersTest.java index 977db939f01..b24202598ae 100644 --- a/webserver/webserver/src/test/java/io/helidon/webserver/http/ErrorHandlersTest.java +++ b/webserver/webserver/src/test/java/io/helidon/webserver/http/ErrorHandlersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. + * Copyright (c) 2022, 2024 Oracle and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import io.helidon.http.Method; import io.helidon.http.Status; import io.helidon.http.media.ReadableEntityBase; +import io.helidon.webserver.CloseConnectionException; import io.helidon.webserver.ConnectionContext; import io.helidon.webserver.ListenerContext; @@ -43,6 +44,8 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -121,6 +124,24 @@ void testHandler() { testNoHandler(handlers, new OtherException(), "Other"); } + @Test + public void testCloseConnectionExceptionContainsCause() { + ConnectionContext ctx = mock(ConnectionContext.class); + RoutingRequest req = mock(RoutingRequest.class); + RoutingResponse res = mock(RoutingResponse.class); + when(res.reset()).thenReturn(false); + ErrorHandlers handlers = ErrorHandlers.create(Map.of(OtherException.class, + (request, response, t) -> res.send(t.getMessage()))); + try { + handlers.runWithErrorHandling(ctx, req, res, () -> { + throw new OtherException(); + }); + fail("It is expected a CloseConnectionException"); + } catch (CloseConnectionException e) { + assertEquals(OtherException.class, e.getCause().getClass()); + } + } + private void testNoHandler(ErrorHandlers handlers, Exception e, String message) { ConnectionContext ctx = mock(ConnectionContext.class); RoutingRequest req = mock(RoutingRequest.class);