Add webflux-netty-tls smoke test
See gh-68
This commit is contained in:
@@ -50,6 +50,7 @@ smoke_tests:
|
||||
- validation
|
||||
- webclient
|
||||
- webflux-netty
|
||||
- webflux-netty-tls
|
||||
- webmvc-tomcat
|
||||
- webmvc-tomcat-tls
|
||||
- websocket
|
||||
|
||||
@@ -78,6 +78,7 @@ include "transactional-event-listener"
|
||||
include "validation"
|
||||
include "webclient"
|
||||
include "webflux-netty"
|
||||
include "webflux-netty-tls"
|
||||
include "webmvc-tomcat"
|
||||
include "webmvc-tomcat-tls"
|
||||
include "websocket"
|
||||
|
||||
1
webflux-netty-tls/README.adoc
Normal file
1
webflux-netty-tls/README.adoc
Normal file
@@ -0,0 +1 @@
|
||||
Tests if WebFlux with Netty with TLS is working
|
||||
22
webflux-netty-tls/build.gradle
Normal file
22
webflux-netty-tls/build.gradle
Normal file
@@ -0,0 +1,22 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot'
|
||||
id 'org.springframework.aot.smoke-test'
|
||||
id 'org.graalvm.buildtools.native'
|
||||
id 'org.jetbrains.kotlin.jvm'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
implementation(project(":aot-smoke-test-third-party-hints"))
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
|
||||
aotTestImplementation(project(":aot-smoke-test-support"))
|
||||
aotTestImplementation("io.projectreactor.netty:reactor-netty")
|
||||
}
|
||||
|
||||
aotSmokeTest {
|
||||
webApplication = true
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.example.webflux.tls;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
|
||||
import org.springframework.aot.smoketest.support.junit.AotSmokeTest;
|
||||
import org.springframework.aot.smoketest.support.junit.ApplicationUrl;
|
||||
import org.springframework.aot.smoketest.support.junit.ApplicationUrl.Scheme;
|
||||
import org.springframework.http.client.reactive.ClientHttpConnector;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import org.springframework.web.reactive.socket.WebSocketMessage;
|
||||
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
|
||||
import org.springframework.web.reactive.socket.client.WebSocketClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@AotSmokeTest
|
||||
class WebFluxNettyTlsApplicationAotTests {
|
||||
|
||||
@Test
|
||||
void stringResponseBody(@ApplicationUrl(scheme = Scheme.HTTPS) URI applicationUrl) throws Exception {
|
||||
WebTestClient client = buildWebClient(applicationUrl);
|
||||
|
||||
client.get().exchange().expectStatus().isOk().expectBody().consumeWith(
|
||||
(result) -> assertThat(new String(result.getResponseBodyContent())).isEqualTo("Hello World TLS"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void websocket(@ApplicationUrl(scheme = Scheme.SECURE_WEBSOCKET) URI applicationUrl) throws Exception {
|
||||
WebSocketClient client = new ReactorNettyWebSocketClient(buildHttpClient());
|
||||
|
||||
// We can't use StepVerifier here, as it isn't designed to be used in a reactive
|
||||
// pipeline
|
||||
AtomicReference<List<String>> messages = new AtomicReference<>();
|
||||
client.execute(URI.create(applicationUrl.resolve("/ws/count").toString()), session -> session.receive()
|
||||
.map(WebSocketMessage::getPayloadAsText).collectList().doOnNext(messages::set).then())
|
||||
.block(Duration.ofSeconds(10));
|
||||
assertThat(messages.get()).isNotNull().containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a web client for the running application. This web client is configured to
|
||||
* trust the TLS certificate of the server.
|
||||
* @param applicationUrl the URL to the application
|
||||
* @return web client
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
private static WebTestClient buildWebClient(URI applicationUrl) throws Exception {
|
||||
ClientHttpConnector connector = new ReactorClientHttpConnector(buildHttpClient());
|
||||
return WebTestClient.bindToServer(connector).baseUrl(applicationUrl.toString()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a http client for the running application. This http client is configured to
|
||||
* trust the TLS certificate of the server.
|
||||
* @return http client
|
||||
* @throws Exception if something went wrong
|
||||
*/
|
||||
private static HttpClient buildHttpClient() throws Exception {
|
||||
KeyStore trustStore = KeyStore.getInstance("jks");
|
||||
try (InputStream stream = WebFluxNettyTlsApplicationAotTests.class.getResourceAsStream("/truststore.jks")) {
|
||||
assertThat(stream).as("Trust store on test classpath").isNotNull();
|
||||
trustStore.load(stream, null);
|
||||
}
|
||||
|
||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory
|
||||
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init(trustStore);
|
||||
|
||||
SslContext sslContext = SslContextBuilder.forClient().trustManager(trustManagerFactory).build();
|
||||
return HttpClient.create().secure((s) -> s.sslContext(sslContext));
|
||||
}
|
||||
|
||||
}
|
||||
BIN
webflux-netty-tls/src/aotTest/resources/truststore.jks
Normal file
BIN
webflux-netty-tls/src/aotTest/resources/truststore.jks
Normal file
Binary file not shown.
@@ -0,0 +1,17 @@
|
||||
package com.example.webflux.tls;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class TestController {
|
||||
|
||||
@GetMapping(value = "/", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
public Mono<String> greet() {
|
||||
return Mono.just("Hello World TLS");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.example.webflux.tls;
|
||||
|
||||
import com.example.webflux.tls.WebFluxNettyTlsApplication.KeyStoreRuntimeHints;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.aot.smoketest.thirdpartyhints.NettyRuntimeHints;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||
|
||||
@SpringBootApplication
|
||||
@ImportRuntimeHints({ NettyRuntimeHints.class, KeyStoreRuntimeHints.class })
|
||||
public class WebFluxNettyTlsApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(WebFluxNettyTlsApplication.class, args);
|
||||
}
|
||||
|
||||
static class KeyStoreRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
hints.resources().registerPattern("keystore.jks");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.example.webflux.tls;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.reactive.socket.WebSocketHandler;
|
||||
import org.springframework.web.reactive.socket.WebSocketMessage;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class WebsocketConfig {
|
||||
|
||||
@Bean
|
||||
WebSocketHandler webSocketHandler() {
|
||||
return webSocketSession -> {
|
||||
Flux<WebSocketMessage> stream = Flux.just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
.map(element -> webSocketSession.textMessage(Integer.toString(element)))
|
||||
.delayElements(Duration.ofMillis(100));
|
||||
return webSocketSession.send(stream);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleUrlHandlerMapping body(WebSocketHandler webSocketHandler) {
|
||||
Map<String, WebSocketHandler> handlers = Map.of("/ws/count", webSocketHandler);
|
||||
return new SimpleUrlHandlerMapping(handlers, 10);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
server.ssl.key-store=classpath:keystore.jks
|
||||
server.ssl.key-store-password=secret
|
||||
server.ssl.key-alias=localhost
|
||||
server.ssl.key-password=secret
|
||||
BIN
webflux-netty-tls/src/main/resources/keystore.jks
Normal file
BIN
webflux-netty-tls/src/main/resources/keystore.jks
Normal file
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
package com.example.webflux.tls;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class WebFluxNettyTlsApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user