diff --git a/docs/src/main/asciidoc/http-reference.adoc b/docs/src/main/asciidoc/http-reference.adoc index 35bf5b1b76922e..90b2d41ffe92bc 100644 --- a/docs/src/main/asciidoc/http-reference.adoc +++ b/docs/src/main/asciidoc/http-reference.adoc @@ -143,6 +143,18 @@ values: NOTE: if you use `redirect` or `disabled` and have not added a SSL certificate or keystore, your server will not start! +== Additional HTTP Headers + +To enable HTTP headers to be sent on every response, add the following properties: + +[source, properties] +---- +quarkus.http.headers."X-Content-Type-Options"=nosniff +---- + +This will include the `X-Content-Type-Options: nosniff` HTTP Header on responses for requests performed on any resource in the application. + + == HTTP/2 Support HTTP/2 is enabled by default, and will be used by browsers if SSL is in use on JDK11 or higher. JDK8 does not support 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 e957143cd6ee85..8b62916ecf73f3 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 @@ -245,6 +245,12 @@ public class HttpConfiguration { @ConfigItem public Optional unhandledErrorContentTypeDefault; + /** + * Additional HTTP Headers always sent in the response + */ + @ConfigItem + public Map headers; + public ProxyConfig proxy; public int determinePort(LaunchMode launchMode) { 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 34c916ad5d043b..85f94367495a6f 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 @@ -360,6 +360,17 @@ public void handle(Void e) { } }); } + // Headers sent on any request, regardless of the response + Map headers = httpConfiguration.headers; + if (!headers.isEmpty()) { + httpRouteRouter.route().order(-1).handler(new Handler() { + @Override + public void handle(RoutingContext event) { + event.response().headers().addAll(headers); + event.next(); + } + }); + } Handler root; if (rootPath.equals("/")) { diff --git a/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/SimpleResource.java b/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/SimpleResource.java index 39571998edd90f..32c1fb948c8e19 100644 --- a/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/SimpleResource.java +++ b/integration-tests/vertx-http/src/main/java/io/quarkus/it/vertx/SimpleResource.java @@ -2,6 +2,7 @@ import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.core.Response; /** * @@ -13,4 +14,16 @@ public class SimpleResource { public String accessLogTest() { return "passed"; } + + @GET + @Path("/headers") + public String headers() { + return "ok"; + } + + @GET + @Path("/headers-override") + public Response headersOverride() { + return Response.ok("ok").header("foo", "abc").build(); + } } diff --git a/integration-tests/vertx-http/src/main/resources/application.properties b/integration-tests/vertx-http/src/main/resources/application.properties index dbdf680151b6e4..78cc3afa2b2151 100644 --- a/integration-tests/vertx-http/src/main/resources/application.properties +++ b/integration-tests/vertx-http/src/main/resources/application.properties @@ -11,4 +11,5 @@ quarkus.http.access-log.enabled=true quarkus.http.access-log.log-to-file=true quarkus.http.access-log.base-file-name=quarkus-access-log quarkus.http.access-log.log-directory=target -quarkus.native.additional-build-args=-H:IncludeResources=.*\\.jks,-H:EnableURLProtocols=http\\,https \ No newline at end of file +quarkus.http.headers.foo=bar +quarkus.native.additional-build-args=-H:IncludeResources=.*\\.jks,-H:EnableURLProtocols=http\\,https diff --git a/integration-tests/vertx-http/src/test/java/io/quarkus/it/vertx/HeadersTestCase.java b/integration-tests/vertx-http/src/test/java/io/quarkus/it/vertx/HeadersTestCase.java new file mode 100644 index 00000000000000..ef8d611d5aaae2 --- /dev/null +++ b/integration-tests/vertx-http/src/test/java/io/quarkus/it/vertx/HeadersTestCase.java @@ -0,0 +1,32 @@ +package io.quarkus.it.vertx; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class HeadersTestCase { + + @Test + void testAdditionalHeaders() { + given() + .get("/simple/headers") + .then() + .header("foo", is("bar")) + .body(is("ok")); + + } + + @Test + void testAdditionalHeadersOverride() { + given() + .get("/simple/headers-override") + .then() + .header("foo", is("abc")) + .body(is("ok")); + + } +}