diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index a5693fcf8283..a324c46bcef8 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -126,6 +126,7 @@ spring-boot-openapi spring-boot-brave spring-boot-simple + spring-boot-http2 diff --git a/spring-boot-modules/spring-boot-http2/pom.xml b/spring-boot-modules/spring-boot-http2/pom.xml new file mode 100644 index 000000000000..9aba813a9227 --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + spring-boot-http2 + 0.0.1-SNAPSHOT + spring-boot-http2 + Demo project for Spring Boot + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-web + + + ch.qos.logback + logback-classic + ${logback.version} + + + ch.qos.logback + logback-core + ${logback.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + -parameters + + + + + + + 3.4.3 + 1.5.17 + + diff --git a/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/Http2Application.java b/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/Http2Application.java new file mode 100644 index 000000000000..a79505fe0c0e --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/Http2Application.java @@ -0,0 +1,13 @@ +package com.baeldung.http2; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Http2Application { + + public static void main(String[] args) { + SpringApplication.run(Http2Application.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/config/Http2Config.java b/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/config/Http2Config.java new file mode 100644 index 000000000000..bacf007f7ac1 --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/config/Http2Config.java @@ -0,0 +1,25 @@ +package com.baeldung.http2.config; + +import org.apache.catalina.connector.Connector; +import org.apache.coyote.http2.Http2Protocol; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("config-class") +public class Http2Config { + + @Bean + public WebServerFactoryCustomizer getWebServerFactoryCustomizer() { + return factory -> { + Connector httpConnector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); + httpConnector.setPort(8080); + factory.addConnectorCustomizers(connector -> connector.addUpgradeProtocol(new Http2Protocol())); + factory.addAdditionalTomcatConnectors(httpConnector); + }; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/controller/Http2Controller.java b/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/controller/Http2Controller.java new file mode 100644 index 000000000000..23af24d3b27e --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/main/java/com/baeldung/http2/controller/Http2Controller.java @@ -0,0 +1,15 @@ +package com.baeldung.http2.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class Http2Controller { + + @GetMapping("/http2/echo") + public String getEcho(@RequestParam String message) { + return message; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-http2/src/main/resources/application-config-class.yml b/spring-boot-modules/spring-boot-http2/src/main/resources/application-config-class.yml new file mode 100644 index 000000000000..fdcfe1c15f8e --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/main/resources/application-config-class.yml @@ -0,0 +1,12 @@ +server: + http2: + enabled: false + + port: 8443 + + ssl: + enabled: true + key-store: classpath:keystore.p12 + key-store-password: abcd1234 + key-store-type: PKCS12 + key-alias: http2-alias \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-http2/src/main/resources/application.yml b/spring-boot-modules/spring-boot-http2/src/main/resources/application.yml new file mode 100644 index 000000000000..e3e6b4a85836 --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/main/resources/application.yml @@ -0,0 +1,12 @@ +server: + http2: + enabled: true + + port: 8443 + + ssl: + enabled: true + key-store: classpath:keystore.p12 + key-store-password: abcd1234 + key-store-type: PKCS12 + key-alias: http2-alias \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-http2/src/main/resources/keystore.p12 b/spring-boot-modules/spring-boot-http2/src/main/resources/keystore.p12 new file mode 100644 index 000000000000..1cf25c4fa9d6 Binary files /dev/null and b/spring-boot-modules/spring-boot-http2/src/main/resources/keystore.p12 differ diff --git a/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/AllCertsTrustManager.java b/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/AllCertsTrustManager.java new file mode 100644 index 000000000000..586810942fc6 --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/AllCertsTrustManager.java @@ -0,0 +1,18 @@ +package com.baeldung.http2; + +import javax.net.ssl.X509TrustManager; +import java.security.cert.X509Certificate; + +public class AllCertsTrustManager implements X509TrustManager { + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/Http2ApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/Http2ApplicationIntegrationTest.java new file mode 100644 index 000000000000..d1e4cc7c27cd --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/Http2ApplicationIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.http2; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import static org.assertj.core.api.Assertions.assertThat; + +// Integration test based on enabling HTTP/2 using the configuration in application.yml +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class Http2ApplicationIntegrationTest { + + private static SSLContext sslContext; + + @LocalServerPort + private int port; + + private HttpClient httpClient; + + @BeforeAll + static void setupOnce() throws NoSuchAlgorithmException, KeyManagementException { + // Get rid of cert validation due to the self-signed certificate + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, + new TrustManager[] { new AllCertsTrustManager() }, + new java.security.SecureRandom()); + } + + @BeforeEach + void setup() { + httpClient = HttpClient.newBuilder() + .sslContext(sslContext) + .version(HttpClient.Version.HTTP_2) + .build(); + } + + @Test + void whenSendHttp2Request_thenReturnHttp2Response() throws Exception { + // when + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(String.format("https://localhost:%s/http2/echo?message=test", port))) + .GET() + .build(); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + + // then + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.body()).isEqualTo("test"); + assertThat(response.version()).isEqualTo(HttpClient.Version.HTTP_2); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/Http2ConfigClassApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/Http2ConfigClassApplicationIntegrationTest.java new file mode 100644 index 000000000000..a475c1e589e0 --- /dev/null +++ b/spring-boot-modules/spring-boot-http2/src/test/java/com/baeldung/http2/Http2ConfigClassApplicationIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.http2; + +import org.springframework.test.context.ActiveProfiles; + +// Integration test based on enabling HTTP/2 using the configuration class Http2Config +@ActiveProfiles("config-class") +class Http2ConfigClassApplicationIntegrationTest extends Http2ApplicationIntegrationTest { +} \ No newline at end of file