diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java
index 5a674e387624c..e957143cd6ee8 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java
@@ -232,14 +232,18 @@ public class HttpConfiguration {
public boolean enableDecompression;
/**
- * Provides a hint (optional) for the contents type of responses generated for
+ * Provides a hint (optional) for the default content type of responses generated for
* the errors not handled by the application.
*
- * When unset, Quarkus will decide which contents type to use based on request headers.
+ * If the client requested a supported content-type in request headers
+ * (e.g. "Accept: application/json", "Accept: text/html"),
+ * Quarkus will use that content type.
+ *
+ * Otherwise, it will default to the content type configured here.
*
*/
@ConfigItem
- public Optional unhandledErrorContentsType;
+ public Optional unhandledErrorContentTypeDefault;
public ProxyConfig proxy;
diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java
index de7b78350be60..bb7b76d586dc2 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java
@@ -40,11 +40,11 @@ public class QuarkusErrorHandler implements Handler {
private static final AtomicLong ERROR_COUNT = new AtomicLong();
private final boolean showStack;
- private final Optional contentTypeHint;
+ private final Optional contentTypeDefault;
- public QuarkusErrorHandler(boolean showStack, Optional contentTypeHint) {
+ public QuarkusErrorHandler(boolean showStack, Optional contentTypeDefault) {
this.showStack = showStack;
- this.contentTypeHint = contentTypeHint;
+ this.contentTypeDefault = contentTypeDefault;
}
@Override
@@ -139,17 +139,6 @@ public void accept(Throwable throwable) {
if (responseContentType == null) {
responseContentType = "";
}
- if (contentTypeHint.isPresent()) {
- switch (contentTypeHint.get()) {
- case JSON:
- jsonResponse(event, ContentTypes.APPLICATION_JSON, details, stack);
- break;
- case HTML:
- htmlResponse(event, details, exception);
- break;
- }
- return;
- }
switch (responseContentType) {
case ContentTypes.TEXT_HTML:
case ContentTypes.APPLICATION_XHTML:
@@ -161,9 +150,16 @@ public void accept(Throwable throwable) {
case ContentTypes.TEXT_JSON:
jsonResponse(event, responseContentType, details, stack);
break;
- // We default to HTML representation
default:
- htmlResponse(event, details, exception);
+ // We default to HTML representation
+ switch (contentTypeDefault.orElse(HttpConfiguration.PayloadHint.HTML)) {
+ case JSON:
+ jsonResponse(event, ContentTypes.APPLICATION_JSON, details, stack);
+ break;
+ case HTML:
+ htmlResponse(event, details, exception);
+ break;
+ }
break;
}
}
diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
index 5376e870eb2b1..4f351e10fe299 100644
--- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
+++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java
@@ -309,7 +309,7 @@ public void finalizeRouter(BeanContainer container, Consumer defaultRoute
}
httpRouteRouter.route().last().failureHandler(
- new QuarkusErrorHandler(launchMode.isDevOrTest(), httpConfiguration.unhandledErrorContentsType));
+ new QuarkusErrorHandler(launchMode.isDevOrTest(), httpConfiguration.unhandledErrorContentTypeDefault));
if (requireBodyHandler) {
//if this is set then everything needs the body handler installed
diff --git a/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java b/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java
index 1a37d1539c8a0..f1634fee29f5f 100644
--- a/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java
+++ b/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java
@@ -50,16 +50,27 @@ public void string_with_quotes_should_be_correctly_escaped() {
}
@Test
- public void json_content_type_hint_should_be_respected() {
+ public void json_content_type_hint_should_be_respected_if_not_accepted() {
QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.JSON));
Mockito.when(routingContext.failure()).thenReturn(testError);
Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any()))
- .thenReturn(new ParsableMIMEValue("text/html").forceParse());
+ .thenReturn(new ParsableMIMEValue("application/foo+json").forceParse());
errorHandler.handle(routingContext);
Mockito.verify(routingContext.response().headers()).set(HttpHeaderNames.CONTENT_TYPE,
"application/json; charset=utf-8");
}
+ @Test
+ public void json_content_type_hint_should_be_ignored_if_accepted() {
+ QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.JSON));
+ Mockito.when(routingContext.failure()).thenReturn(testError);
+ Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any()))
+ .thenReturn(new ParsableMIMEValue("text/html").forceParse());
+ errorHandler.handle(routingContext);
+ Mockito.verify(routingContext.response().headers()).set(HttpHeaderNames.CONTENT_TYPE,
+ "text/html; charset=utf-8");
+ }
+
@Test
public void content_type_should_default_to_json_if_accepted() {
QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.empty());
@@ -72,15 +83,26 @@ public void content_type_should_default_to_json_if_accepted() {
}
@Test
- public void html_content_type_hint_should_be_respected() {
+ public void html_content_type_hint_should_be_respected_if_not_accepted() {
QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.HTML));
Mockito.when(routingContext.failure()).thenReturn(testError);
Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any()))
- .thenReturn(new ParsableMIMEValue("application/json").forceParse());
+ .thenReturn(new ParsableMIMEValue("application/foo+json").forceParse());
errorHandler.handle(routingContext);
Mockito.verify(routingContext.response().headers()).set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8");
}
+ @Test
+ public void html_content_type_hint_should_be_ignored_if_accepted() {
+ QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.HTML));
+ Mockito.when(routingContext.failure()).thenReturn(testError);
+ Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any()))
+ .thenReturn(new ParsableMIMEValue("application/json").forceParse());
+ errorHandler.handle(routingContext);
+ Mockito.verify(routingContext.response().headers()).set(HttpHeaderNames.CONTENT_TYPE,
+ "application/json; charset=utf-8");
+ }
+
@Test
public void content_type_should_default_to_html_if_accepted() {
QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.empty());