From bc7195d00d00bbd76c6dd5f4e966f39b851f05c5 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Thu, 20 Jul 2023 14:02:01 +0200 Subject: [PATCH] Use httpbin as docker compose service Closes gh-184 --- framework/rest-template/docker-compose.yml | 23 +++++++-- framework/rest-template/server.crt | 15 ++++++ framework/rest-template/server.key | 9 ++++ .../RestTemplateApplicationAotTests.java | 6 ++- .../java/com/example/resttemplate/CLR.java | 29 ++++++----- .../com/example/resttemplate/DataDto.java | 33 +++++++++++++ framework/webclient/docker-compose.yml | 23 +++++++-- framework/webclient/server.crt | 15 ++++++ framework/webclient/server.key | 9 ++++ .../WebClientApplicationAotTests.java | 21 ++++---- .../main/java/com/example/webclient/CLR.java | 22 +++++---- .../java/com/example/webclient/DataDto.java | 33 +++++++++++++ .../com/example/webclient/DataService.java | 4 +- .../example/webclient/ExchangeDataDto.java | 33 +++++++++++++ .../webclient/WebClientConfiguration.java | 48 ++++++------------- 15 files changed, 247 insertions(+), 76 deletions(-) create mode 100644 framework/rest-template/server.crt create mode 100644 framework/rest-template/server.key create mode 100644 framework/rest-template/src/main/java/com/example/resttemplate/DataDto.java create mode 100644 framework/webclient/server.crt create mode 100644 framework/webclient/server.key create mode 100644 framework/webclient/src/main/java/com/example/webclient/DataDto.java create mode 100644 framework/webclient/src/main/java/com/example/webclient/ExchangeDataDto.java diff --git a/framework/rest-template/docker-compose.yml b/framework/rest-template/docker-compose.yml index b03a0fc4..880a773d 100644 --- a/framework/rest-template/docker-compose.yml +++ b/framework/rest-template/docker-compose.yml @@ -1,7 +1,22 @@ version: '3' services: - httpecho: - image: 'mhalbritter/http-echo:2' + httpbin: + image: 'mccutchen/go-httpbin:v2.10.0' ports: - - '80' - - '443' + - '8080' + httpbin_tls: + image: 'mccutchen/go-httpbin:v2.10.0' + environment: + - 'PORT=8443' + - 'HTTPS_CERT_FILE=/server-certificate' + - 'HTTPS_KEY_FILE=/server-key' + configs: + - 'server-certificate' + - 'server-key' + ports: + - '8443' +configs: + server-certificate: + file: './server.crt' + server-key: + file: './server.key' diff --git a/framework/rest-template/server.crt b/framework/rest-template/server.crt new file mode 100644 index 00000000..fdd0a772 --- /dev/null +++ b/framework/rest-template/server.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQDCCAcagAwIBAgIUJL2NEOsGlUgyKo3jUur8gol3ymowCgYIKoZIzj0EAwIw +VjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwT +RGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIzMDYy +NjA4MzY0NFoYDzIxMjMwNjAyMDgzNjQ0WjBWMQswCQYDVQQGEwJYWDEVMBMGA1UE +BwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMRIw +EAYDVQQDDAlsb2NhbGhvc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARm10hC6jI0 +tA5dVYyYLsaS+rDXaFDbtspX/mxHk5VTfklPD06L3sXcNJeve6YQHlOTwdUzLi2y +iGuaVcljlA31iOtfQEATeSdbeFxxLjM22U+FZJ94j14XrbemtpspuTujUzBRMB0G +A1UdDgQWBBQEfrPdmYvL/w5sLHWL0eVj0f1M0DAfBgNVHSMEGDAWgBQEfrPdmYvL +/w5sLHWL0eVj0f1M0DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA2gAMGUC +MHtVMoEKtgkOcv2fhrv0788S/yIRa6PBt8nxMa6d7mDTFGkMhBCIG168pJk9nHE+ +vgIxAJ1JF2uB5PYV5nYwliOttnb8LMza7hhun1EVsfKuFgvMUD3VTgtZJ9PE4c8I +pxq8IA== +-----END CERTIFICATE----- diff --git a/framework/rest-template/server.key b/framework/rest-template/server.key new file mode 100644 index 00000000..998c9c23 --- /dev/null +++ b/framework/rest-template/server.key @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCVOy3osulJ/8y+ckbBc0dAdSiLFiRcU1SFqWWsmoaCKexSBOgA8/vG +DFFqYvummn6gBwYFK4EEACKhZANiAARm10hC6jI0tA5dVYyYLsaS+rDXaFDbtspX +/mxHk5VTfklPD06L3sXcNJeve6YQHlOTwdUzLi2yiGuaVcljlA31iOtfQEATeSdb +eFxxLjM22U+FZJ94j14XrbemtpspuTs= +-----END EC PRIVATE KEY----- diff --git a/framework/rest-template/src/appTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java b/framework/rest-template/src/appTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java index a184d08f..9a35fa19 100644 --- a/framework/rest-template/src/appTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java +++ b/framework/rest-template/src/appTest/java/com/example/resttemplate/RestTemplateApplicationAotTests.java @@ -19,14 +19,16 @@ class RestTemplateApplicationAotTests { void httpWorks(AssertableOutput output) { Awaitility.await() .atMost(Duration.ofSeconds(30)) - .untilAsserted(() -> assertThat(output).hasSingleLineContaining("http worked:")); + .untilAsserted(() -> assertThat(output) + .hasLineMatching("http: DataDto\\{url='http:\\/\\/\\w+:\\d+\\/anything', method='GET'\\}")); } @Test void httpsWorks(AssertableOutput output) { Awaitility.await() .atMost(Duration.ofSeconds(30)) - .untilAsserted(() -> assertThat(output).hasSingleLineContaining("https worked:")); + .untilAsserted(() -> assertThat(output) + .hasLineMatching("https: DataDto\\{url='https:\\/\\/\\w+:\\d+\\/anything', method='GET'\\}")); } } diff --git a/framework/rest-template/src/main/java/com/example/resttemplate/CLR.java b/framework/rest-template/src/main/java/com/example/resttemplate/CLR.java index b42c95fe..79b037b9 100644 --- a/framework/rest-template/src/main/java/com/example/resttemplate/CLR.java +++ b/framework/rest-template/src/main/java/com/example/resttemplate/CLR.java @@ -2,27 +2,32 @@ import java.net.URI; +import org.springframework.aot.hint.annotation.RegisterReflectionForBinding; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; @Component +@RegisterReflectionForBinding(DataDto.class) class CLR implements CommandLineRunner { private final RestTemplate restTemplate; - private final String host; + private final String httpHost; - private final int port; + private final int httpPort; - private final int tlsPort; + private final String httpsHost; + + private final int httpsPort; CLR(RestTemplate restTemplate) { this.restTemplate = restTemplate; - this.host = env("HTTPECHO_HOST", "localhost"); - this.port = env("HTTPECHO_PORT_80", 8080); - this.tlsPort = env("HTTPECHO_PORT_443", 8443); + this.httpHost = env("HTTPBIN_HOST", "localhost"); + this.httpsHost = env("HTTPBIN_TLS_HOST", "localhost"); + this.httpPort = env("HTTPBIN_PORT_8080", 8080); + this.httpsPort = env("HTTPBIN_TLS_PORT_8443", 8443); } @Override @@ -33,9 +38,9 @@ public void run(String... args) { private void http() { try { - String response = this.restTemplate - .getForObject(URI.create("http://%s:%d/".formatted(this.host, this.port)), String.class); - System.out.printf("http worked: %s%n", response); + DataDto dto = restTemplate.getForObject( + URI.create("http://%s:%d/anything".formatted(this.httpHost, this.httpPort)), DataDto.class); + System.out.printf("http: %s%n", dto); } catch (Exception ex) { System.out.println("http failed:"); @@ -45,9 +50,9 @@ private void http() { private void https() { try { - String response = this.restTemplate - .getForObject(URI.create("https://%s:%d/".formatted(this.host, this.tlsPort)), String.class); - System.out.printf("https worked: %s%n", response); + DataDto dto = restTemplate.getForObject( + URI.create("https://%s:%d/anything".formatted(this.httpsHost, this.httpsPort)), DataDto.class); + System.out.printf("https: %s%n", dto); } catch (Exception ex) { System.out.println("https failed:"); diff --git a/framework/rest-template/src/main/java/com/example/resttemplate/DataDto.java b/framework/rest-template/src/main/java/com/example/resttemplate/DataDto.java new file mode 100644 index 00000000..39442b47 --- /dev/null +++ b/framework/rest-template/src/main/java/com/example/resttemplate/DataDto.java @@ -0,0 +1,33 @@ +package com.example.resttemplate; + +public class DataDto { + + private String url; + + private String method; + + public DataDto() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public String toString() { + return "DataDto{" + "url='" + url + '\'' + ", method='" + method + '\'' + '}'; + } + +} diff --git a/framework/webclient/docker-compose.yml b/framework/webclient/docker-compose.yml index b03a0fc4..880a773d 100644 --- a/framework/webclient/docker-compose.yml +++ b/framework/webclient/docker-compose.yml @@ -1,7 +1,22 @@ version: '3' services: - httpecho: - image: 'mhalbritter/http-echo:2' + httpbin: + image: 'mccutchen/go-httpbin:v2.10.0' ports: - - '80' - - '443' + - '8080' + httpbin_tls: + image: 'mccutchen/go-httpbin:v2.10.0' + environment: + - 'PORT=8443' + - 'HTTPS_CERT_FILE=/server-certificate' + - 'HTTPS_KEY_FILE=/server-key' + configs: + - 'server-certificate' + - 'server-key' + ports: + - '8443' +configs: + server-certificate: + file: './server.crt' + server-key: + file: './server.key' diff --git a/framework/webclient/server.crt b/framework/webclient/server.crt new file mode 100644 index 00000000..fdd0a772 --- /dev/null +++ b/framework/webclient/server.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICQDCCAcagAwIBAgIUJL2NEOsGlUgyKo3jUur8gol3ymowCgYIKoZIzj0EAwIw +VjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwT +RGVmYXVsdCBDb21wYW55IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTIzMDYy +NjA4MzY0NFoYDzIxMjMwNjAyMDgzNjQ0WjBWMQswCQYDVQQGEwJYWDEVMBMGA1UE +BwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMRIw +EAYDVQQDDAlsb2NhbGhvc3QwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARm10hC6jI0 +tA5dVYyYLsaS+rDXaFDbtspX/mxHk5VTfklPD06L3sXcNJeve6YQHlOTwdUzLi2y +iGuaVcljlA31iOtfQEATeSdbeFxxLjM22U+FZJ94j14XrbemtpspuTujUzBRMB0G +A1UdDgQWBBQEfrPdmYvL/w5sLHWL0eVj0f1M0DAfBgNVHSMEGDAWgBQEfrPdmYvL +/w5sLHWL0eVj0f1M0DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA2gAMGUC +MHtVMoEKtgkOcv2fhrv0788S/yIRa6PBt8nxMa6d7mDTFGkMhBCIG168pJk9nHE+ +vgIxAJ1JF2uB5PYV5nYwliOttnb8LMza7hhun1EVsfKuFgvMUD3VTgtZJ9PE4c8I +pxq8IA== +-----END CERTIFICATE----- diff --git a/framework/webclient/server.key b/framework/webclient/server.key new file mode 100644 index 00000000..998c9c23 --- /dev/null +++ b/framework/webclient/server.key @@ -0,0 +1,9 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCVOy3osulJ/8y+ckbBc0dAdSiLFiRcU1SFqWWsmoaCKexSBOgA8/vG +DFFqYvummn6gBwYFK4EEACKhZANiAARm10hC6jI0tA5dVYyYLsaS+rDXaFDbtspX +/mxHk5VTfklPD06L3sXcNJeve6YQHlOTwdUzLi2yiGuaVcljlA31iOtfQEATeSdb +eFxxLjM22U+FZJ94j14XrbemtpspuTs= +-----END EC PRIVATE KEY----- diff --git a/framework/webclient/src/appTest/java/com/example/webclient/WebClientApplicationAotTests.java b/framework/webclient/src/appTest/java/com/example/webclient/WebClientApplicationAotTests.java index 9e3273bb..1fa26b44 100644 --- a/framework/webclient/src/appTest/java/com/example/webclient/WebClientApplicationAotTests.java +++ b/framework/webclient/src/appTest/java/com/example/webclient/WebClientApplicationAotTests.java @@ -17,23 +17,26 @@ class WebClientApplicationAotTests { @Test @DisabledIfEnvironmentVariable(named = "CI", matches = "true", disabledReason = "HTTP is blocked on CI") void httpWorks(AssertableOutput output) { - Awaitility.await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> { - assertThat(output).hasSingleLineContaining("https worked:"); - }); + Awaitility.await() + .atMost(Duration.ofSeconds(30)) + .untilAsserted(() -> assertThat(output) + .hasLineMatching("http: DataDto\\{url='http:\\/\\/\\w+:\\d+\\/anything', method='GET'\\}")); } @Test void httpsWorks(AssertableOutput output) { - Awaitility.await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> { - assertThat(output).hasSingleLineContaining("https worked:"); - }); + Awaitility.await() + .atMost(Duration.ofSeconds(30)) + .untilAsserted(() -> assertThat(output) + .hasLineMatching("https: DataDto\\{url='https:\\/\\/\\w+:\\d+\\/anything', method='GET'\\}")); } @Test void serviceWorks(AssertableOutput output) { - Awaitility.await().atMost(Duration.ofSeconds(30)).untilAsserted(() -> { - assertThat(output).hasSingleLineContaining("service worked:"); - }); + Awaitility.await() + .atMost(Duration.ofSeconds(30)) + .untilAsserted(() -> assertThat(output) + .hasLineMatching("service: ExchangeDataDto\\{url='http:\\/\\/\\w+:\\d+\\/anything', method='GET'\\}")); } } diff --git a/framework/webclient/src/main/java/com/example/webclient/CLR.java b/framework/webclient/src/main/java/com/example/webclient/CLR.java index 162c440a..7ddcbd2c 100644 --- a/framework/webclient/src/main/java/com/example/webclient/CLR.java +++ b/framework/webclient/src/main/java/com/example/webclient/CLR.java @@ -2,12 +2,14 @@ import java.time.Duration; +import org.springframework.aot.hint.annotation.RegisterReflectionForBinding; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; @Component +@RegisterReflectionForBinding(DataDto.class) class CLR implements CommandLineRunner { private final WebClient httpWebClient; @@ -32,13 +34,13 @@ public void run(String... args) { private void http() { try { - String response = this.httpWebClient.get() - .uri("/") + DataDto dto = this.httpWebClient.get() + .uri("/anything") .retrieve() - .bodyToMono(String.class) + .bodyToMono(DataDto.class) .timeout(Duration.ofSeconds(10)) .block(); - System.out.printf("http worked: %s%n", response); + System.out.printf("http: %s%n", dto); } catch (Exception ex) { System.out.println("http failed:"); @@ -48,13 +50,13 @@ private void http() { private void https() { try { - String response = this.httpsWebClient.get() - .uri("/") + DataDto dto = this.httpsWebClient.get() + .uri("/anything") .retrieve() - .bodyToMono(String.class) + .bodyToMono(DataDto.class) .timeout(Duration.ofSeconds(10)) .block(); - System.out.printf("https worked: %s%n", response); + System.out.printf("https: %s%n", dto); } catch (Exception ex) { System.out.println("https failed:"); @@ -64,8 +66,8 @@ private void https() { private void service() { try { - String dto = this.dataService.getData(); - System.out.printf("service worked: %s%n", dto); + ExchangeDataDto dto = this.dataService.getData(); + System.out.printf("service: %s%n", dto); } catch (Exception ex) { System.out.println("service failed:"); diff --git a/framework/webclient/src/main/java/com/example/webclient/DataDto.java b/framework/webclient/src/main/java/com/example/webclient/DataDto.java new file mode 100644 index 00000000..4e9e45ae --- /dev/null +++ b/framework/webclient/src/main/java/com/example/webclient/DataDto.java @@ -0,0 +1,33 @@ +package com.example.webclient; + +public class DataDto { + + private String url; + + private String method; + + public DataDto() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public String toString() { + return "DataDto{" + "url='" + url + '\'' + ", method='" + method + '\'' + '}'; + } + +} diff --git a/framework/webclient/src/main/java/com/example/webclient/DataService.java b/framework/webclient/src/main/java/com/example/webclient/DataService.java index ebfcf198..96048075 100644 --- a/framework/webclient/src/main/java/com/example/webclient/DataService.java +++ b/framework/webclient/src/main/java/com/example/webclient/DataService.java @@ -4,7 +4,7 @@ interface DataService { - @GetExchange("/") - String getData(); + @GetExchange("/anything") + ExchangeDataDto getData(); } diff --git a/framework/webclient/src/main/java/com/example/webclient/ExchangeDataDto.java b/framework/webclient/src/main/java/com/example/webclient/ExchangeDataDto.java new file mode 100644 index 00000000..5eb1b045 --- /dev/null +++ b/framework/webclient/src/main/java/com/example/webclient/ExchangeDataDto.java @@ -0,0 +1,33 @@ +package com.example.webclient; + +public class ExchangeDataDto { + + private String url; + + private String method; + + public ExchangeDataDto() { + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public String toString() { + return "ExchangeDataDto{" + "url='" + url + '\'' + ", method='" + method + '\'' + '}'; + } + +} diff --git a/framework/webclient/src/main/java/com/example/webclient/WebClientConfiguration.java b/framework/webclient/src/main/java/com/example/webclient/WebClientConfiguration.java index 643f3cbf..9d4c6ed7 100644 --- a/framework/webclient/src/main/java/com/example/webclient/WebClientConfiguration.java +++ b/framework/webclient/src/main/java/com/example/webclient/WebClientConfiguration.java @@ -19,27 +19,26 @@ @Configuration(proxyBeanMethods = false) class WebClientConfiguration { - @Bean - HttpEchoConfig httpEchoConfig() { - return HttpEchoConfig.loadFromEnv(); - } - @Bean @Qualifier("https") - WebClient webClientHttps(HttpEchoConfig httpEchoConfig, WebClient.Builder builder) throws SSLException { + WebClient webClientHttps(WebClient.Builder builder) throws SSLException { SslContext sslContext = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) .build(); HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); - return builder.baseUrl(httpEchoConfig.httpsBaseUrl()) + String host = env("HTTPBIN_TLS_HOST", "localhost"); + int port = env("HTTPBIN_TLS_PORT_8443", 8443); + return builder.baseUrl("https://%s:%d/".formatted(host, port)) .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); } @Bean @Qualifier("http") - WebClient webClientHttp(HttpEchoConfig httpEchoConfig, WebClient.Builder builder) { - return builder.baseUrl(httpEchoConfig.httpBaseUrl()).build(); + WebClient webClientHttp(WebClient.Builder builder) { + String host = env("HTTPBIN_HOST", "localhost"); + int port = env("HTTPBIN_PORT_8080", 8080); + return builder.baseUrl("http://%s:%d/".formatted(host, port)).build(); } @Bean @@ -49,31 +48,14 @@ DataService dataService(@Qualifier("http") WebClient webClient) { return factory.createClient(DataService.class); } - record HttpEchoConfig(String host, int port, int tlsPort) { - public static HttpEchoConfig loadFromEnv() { - String host = env("HTTPECHO_HOST", "localhost"); - int port = env("HTTPECHO_PORT_80", 8080); - int tlsPort = env("HTTPECHO_PORT_443", 8443); - return new HttpEchoConfig(host, port, tlsPort); - } - - String httpsBaseUrl() { - return "https://%s:%d/".formatted(this.host, this.tlsPort); - } - - String httpBaseUrl() { - return "http://%s:%d/".formatted(this.host, this.port); - } - - private static String env(String name, String def) { - String value = System.getenv(name); - return StringUtils.hasLength(value) ? value : def; - } + private static String env(String name, String def) { + String value = System.getenv(name); + return StringUtils.hasLength(value) ? value : def; + } - private static int env(String name, int def) { - String value = System.getenv(name); - return StringUtils.hasLength(value) ? Integer.parseInt(value) : def; - } + private static int env(String name, int def) { + String value = System.getenv(name); + return StringUtils.hasLength(value) ? Integer.parseInt(value) : def; } }