diff --git a/http-server-netty/src/test/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProviderTest.java b/http-server-netty/src/test/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProviderTest.java index 328d67c794b..a5a186c524a 100644 --- a/http-server-netty/src/test/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProviderTest.java +++ b/http-server-netty/src/test/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProviderTest.java @@ -6,17 +6,17 @@ import io.micronaut.context.annotation.Requires; import io.micronaut.context.i18n.ResourceBundleMessageSource; import io.micronaut.core.annotation.Introspected; +import io.micronaut.core.annotation.NonNull; import io.micronaut.http.*; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.annotation.Status; +import io.micronaut.http.annotation.*; import io.micronaut.http.client.BlockingHttpClient; import io.micronaut.http.client.HttpClient; import io.micronaut.http.client.annotation.Client; import io.micronaut.http.client.exceptions.HttpClientResponseException; +import io.micronaut.http.server.exceptions.ErrorResponseProcessorExceptionHandler; +import io.micronaut.http.server.exceptions.ExceptionHandler; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import jakarta.annotation.security.PermitAll; import jakarta.inject.Inject; import jakarta.inject.Singleton; import jakarta.validation.Valid; @@ -100,6 +100,14 @@ void validationErrorsShowInHtmlErrorPages() { assertExpectedSubstringInHtml("Es posible que haya escrito mal la dirección o que la página se haya movido.", html); } + @Test + void userNotFoundExceptionHandlerReturnsNotFound(@Client("/") HttpClient httpClient) { + BlockingHttpClient client = httpClient.toBlocking(); + HttpClientResponseException ex = assertThrows(HttpClientResponseException.class, + () -> client.exchange(HttpRequest.GET("/throws").accept(MediaType.TEXT_HTML))); + assertEquals(HttpStatus.NOT_FOUND, ex.getStatus()); + } + private void assertExpectedSubstringInHtml(String expected, String html) { if (!html.contains(expected)) { LOG.trace("{}", html); @@ -131,4 +139,34 @@ MessageSource createMessageSource() { @Introspected record Book(@NotBlank String title, @NotBlank String author, @Max(4032) int pages) { } + + static class UserNotFoundException extends RuntimeException { + } + + @Requires(property = "spec.name", value = "DefaultHtmlBodyErrorResponseProviderTest") + @Produces + @Singleton + @Requires(classes = {UserNotFoundException.class, ExceptionHandler.class}) + static class UserNotFoundExceptionHandler extends ErrorResponseProcessorExceptionHandler { + protected UserNotFoundExceptionHandler(ErrorResponseProcessor responseProcessor) { + super(responseProcessor); + } + + @Override + protected @NonNull MutableHttpResponse createResponse(UserNotFoundException exception) { + return HttpResponse.notFound(); + } + } + + @Requires(property = "spec.name", value = "DefaultHtmlBodyErrorResponseProviderTest") + @Controller("/throws") + static class ThrowingController { + @Produces(MediaType.TEXT_HTML) + @PermitAll + @Get + @Status(HttpStatus.OK) + void index() { + throw new UserNotFoundException(); + } + } } diff --git a/http-server/src/main/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProvider.java b/http-server/src/main/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProvider.java index 53115a5544c..39e2e40b4b5 100644 --- a/http-server/src/main/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProvider.java +++ b/http-server/src/main/java/io/micronaut/http/server/exceptions/response/DefaultHtmlErrorResponseBodyProvider.java @@ -20,6 +20,7 @@ import io.micronaut.core.annotation.Internal; import io.micronaut.core.annotation.NonNull; import io.micronaut.core.util.LocaleResolver; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; @@ -177,7 +178,7 @@ private HtmlErrorPage error(@NonNull ErrorContext errorContext, List messages = new ArrayList<>(); for (io.micronaut.http.server.exceptions.response.Error e : errorContext.getErrors()) { - if (!e.getMessage().equalsIgnoreCase(httpStatusReason)) { + if (StringUtils.isNotEmpty(e.getMessage()) && !e.getMessage().equalsIgnoreCase(httpStatusReason)) { messages.add(htmlSanitizer.sanitize(e.getMessage())); } }