diff --git a/client/src/test/java/org/asynchttpclient/proxy/HttpsProxyTestcontainersIntegrationTest.java b/client/src/test/java/org/asynchttpclient/proxy/HttpsProxyTestcontainersIntegrationTest.java index 683e74c905..2107d74ce2 100644 --- a/client/src/test/java/org/asynchttpclient/proxy/HttpsProxyTestcontainersIntegrationTest.java +++ b/client/src/test/java/org/asynchttpclient/proxy/HttpsProxyTestcontainersIntegrationTest.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.testcontainers.DockerClientFactory; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; @@ -53,11 +54,12 @@ public class HttpsProxyTestcontainersIntegrationTest { private static final int SQUID_HTTP_PORT = 3128; private static final int SQUID_HTTPS_PORT = 3129; - private static final String TARGET_HTTP_URL = "http://httpbin.org/get"; - private static final String TARGET_HTTPS_URL = "https://www.example.com/"; - private static boolean dockerAvailable = false; + private static Network network; + private static GenericContainer targetServer; private static GenericContainer squidProxy; + private static String targetHttpUrl; + private static String targetHttpsUrl; @BeforeAll static void checkDockerAvailability() { @@ -76,13 +78,21 @@ static void checkDockerAvailability() { if ("true".equals(System.getProperty("no.docker.tests"))) { assumeTrue(false, "Docker tests disabled via -Dno.docker.tests=true"); } - // Only start container if Docker is available + // Only start containers if Docker is available if (dockerAvailable) { + network = Network.newNetwork(); + targetServer = LocalProxyTestTarget.start(network); + String targetIp = LocalProxyTestTarget.networkIpOf(targetServer); + targetHttpUrl = "http://" + targetIp + "/get"; + targetHttpsUrl = "https://" + targetIp + "/"; + LOGGER.info("Local proxy target started at {} / {}", targetHttpUrl, targetHttpsUrl); + squidProxy = new GenericContainer<>( new ImageFromDockerfile() .withFileFromPath("Dockerfile", Path.of("src/test/resources/squid/Dockerfile")) .withFileFromPath("squid.conf", Path.of("src/test/resources/squid/squid.conf")) ) + .withNetwork(network) .withExposedPorts(SQUID_HTTP_PORT, SQUID_HTTPS_PORT) .withLogConsumer(new Slf4jLogConsumer(LOGGER).withPrefix("SQUID")) .waitingFor(Wait.forLogMessage(".*Accepting HTTP.*", 1) @@ -96,6 +106,12 @@ static void stopContainer() { if (squidProxy != null && squidProxy.isRunning()) { squidProxy.stop(); } + if (targetServer != null && targetServer.isRunning()) { + targetServer.stop(); + } + if (network != null) { + network.close(); + } } @RepeatedIfExceptionsTest(repeats = 3) @@ -110,9 +126,9 @@ public void testHttpProxyToHttpTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTP_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("httpbin")); + assertTrue(response.getResponseBody().contains(LocalProxyTestTarget.BODY_MARKER)); LOGGER.info("HTTP proxy to HTTP target test passed"); } } @@ -130,9 +146,9 @@ public void testHttpsProxyToHttpTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTP_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("httpbin")); + assertTrue(response.getResponseBody().contains(LocalProxyTestTarget.BODY_MARKER)); LOGGER.info("HTTPS proxy to HTTP target test passed"); } } @@ -150,10 +166,9 @@ public void testHttpProxyToHttpsTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTPS_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpsUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("Example Domain") || - response.getResponseBody().contains("example")); + assertTrue(response.getResponseBody().contains("AHC Test Target")); LOGGER.info("HTTP proxy to HTTPS target test passed"); } } @@ -171,10 +186,9 @@ public void testHttpsProxyToHttpsTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTPS_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpsUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("Example Domain") || - response.getResponseBody().contains("example")); + assertTrue(response.getResponseBody().contains("AHC Test Target")); LOGGER.info("HTTPS proxy to HTTPS target test passed - core issue #1907 RESOLVED!"); } } diff --git a/client/src/test/java/org/asynchttpclient/proxy/LocalProxyTestTarget.java b/client/src/test/java/org/asynchttpclient/proxy/LocalProxyTestTarget.java new file mode 100644 index 0000000000..807de54b40 --- /dev/null +++ b/client/src/test/java/org/asynchttpclient/proxy/LocalProxyTestTarget.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2026 AsyncHttpClient Project. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.asynchttpclient.proxy; + +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; + +final class LocalProxyTestTarget { + + static final int HTTP_PORT = 80; + static final int HTTPS_PORT = 443; + static final String BODY_MARKER = "ahc-test-target"; + + private LocalProxyTestTarget() { + } + + static GenericContainer start(Network network) { + GenericContainer target = new GenericContainer<>(DockerImageName.parse("nginx:1.27-alpine")) + .withNetwork(network) + .withNetworkAliases("ahc-test-target") + .withCopyFileToContainer(MountableFile.forClasspathResource("proxy-target/nginx.conf", 0644), "/etc/nginx/nginx.conf") + .withCopyFileToContainer(MountableFile.forClasspathResource("proxy-target/server.crt", 0644), "/etc/nginx/certs/server.crt") + .withCopyFileToContainer(MountableFile.forClasspathResource("proxy-target/server.key", 0644), "/etc/nginx/certs/server.key") + .withExposedPorts(HTTP_PORT, HTTPS_PORT) + .waitingFor(Wait.forListeningPorts(HTTP_PORT, HTTPS_PORT)); + target.start(); + return target; + } + + static String networkIpOf(GenericContainer container) { + return container.getContainerInfo().getNetworkSettings().getNetworks().values().stream() + .map(n -> n.getIpAddress()) + .filter(ip -> ip != null && !ip.isEmpty()) + .findFirst() + .orElseThrow(() -> new IllegalStateException("target container has no network IP")); + } +} diff --git a/client/src/test/java/org/asynchttpclient/proxy/ProxyTest.java b/client/src/test/java/org/asynchttpclient/proxy/ProxyTest.java index 14da96360f..73d7f6a598 100644 --- a/client/src/test/java/org/asynchttpclient/proxy/ProxyTest.java +++ b/client/src/test/java/org/asynchttpclient/proxy/ProxyTest.java @@ -319,9 +319,10 @@ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { @RepeatedIfExceptionsTest(repeats = 5) public void runSocksProxy() throws Exception { + SocksProxy socksProxy = new SocksProxy(60000); new Thread(() -> { try { - new SocksProxy(60000); + socksProxy.run(); } catch (IOException e) { logger.error("Failed to establish SocksProxy", e); } @@ -330,10 +331,12 @@ public void runSocksProxy() throws Exception { try (AsyncHttpClient client = asyncHttpClient()) { String target = "http://localhost:" + port1 + '/'; Future f = client.prepareGet(target) - .setProxyServer(new ProxyServer.Builder("localhost", 8000).setProxyType(ProxyType.SOCKS_V4)) + .setProxyServer(new ProxyServer.Builder("localhost", socksProxy.getPort()).setProxyType(ProxyType.SOCKS_V4)) .execute(); assertEquals(200, f.get(60, TimeUnit.SECONDS).getStatusCode()); + } finally { + socksProxy.stop(); } } diff --git a/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTest.java b/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTest.java index 75b2e7e74c..4af5fb4891 100644 --- a/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTest.java +++ b/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTest.java @@ -60,28 +60,26 @@ private static int findFreePort() throws IOException { @RepeatedIfExceptionsTest(repeats = 5) public void testSocks4ProxyWithHttp() throws Exception { - // Start SOCKS proxy in background thread - Thread socksProxyThread = new Thread(() -> { + SocksProxy socksProxy = new SocksProxy(60000); + new Thread(() -> { try { - new SocksProxy(60000); + socksProxy.run(); } catch (Exception e) { logger.error("Failed to establish SocksProxy", e); } - }); - socksProxyThread.start(); - - // Give the proxy time to start - Thread.sleep(1000); + }).start(); try (AsyncHttpClient client = asyncHttpClient()) { String target = "http://localhost:" + port1 + '/'; Future f = client.prepareGet(target) - .setProxyServer(new ProxyServer.Builder("localhost", 8000).setProxyType(ProxyType.SOCKS_V4)) + .setProxyServer(new ProxyServer.Builder("localhost", socksProxy.getPort()).setProxyType(ProxyType.SOCKS_V4)) .execute(); Response response = f.get(60, TimeUnit.SECONDS); assertNotNull(response); assertEquals(200, response.getStatusCode()); + } finally { + socksProxy.stop(); } } diff --git a/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTestcontainersIntegrationTest.java b/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTestcontainersIntegrationTest.java index 1d1a9fa770..4c07456ff3 100644 --- a/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTestcontainersIntegrationTest.java +++ b/client/src/test/java/org/asynchttpclient/proxy/SocksProxyTestcontainersIntegrationTest.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.testcontainers.DockerClientFactory; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; @@ -56,11 +57,12 @@ public class SocksProxyTestcontainersIntegrationTest { private static final int SOCKS_PORT = 1080; - private static final String TARGET_HTTP_URL = "http://httpbin.org/get"; - private static final String TARGET_HTTPS_URL = "https://www.example.com/"; - private static boolean dockerAvailable = false; + private static Network network; + private static GenericContainer targetServer; private static GenericContainer socksProxy; + private static String targetHttpUrl; + private static String targetHttpsUrl; @BeforeAll static void checkDockerAvailability() { @@ -82,14 +84,22 @@ static void checkDockerAvailability() { dockerAvailable = false; return; } - // Only start container if Docker is available + // Only start containers if Docker is available if (dockerAvailable) { try { + network = Network.newNetwork(); + targetServer = LocalProxyTestTarget.start(network); + String targetIp = LocalProxyTestTarget.networkIpOf(targetServer); + targetHttpUrl = "http://" + targetIp + "/get"; + targetHttpsUrl = "https://" + targetIp + "/"; + LOGGER.info("Local proxy target started at {} / {}", targetHttpUrl, targetHttpsUrl); + socksProxy = new GenericContainer<>( new ImageFromDockerfile() .withFileFromPath("Dockerfile", Path.of("src/test/resources/dante/Dockerfile")) .withFileFromPath("sockd.conf", Path.of("src/test/resources/dante/sockd.conf")) ) + .withNetwork(network) .withExposedPorts(SOCKS_PORT) .withLogConsumer(new Slf4jLogConsumer(LOGGER).withPrefix("DANTE")) .waitingFor(Wait.forLogMessage(".*danted.*running.*", 1) @@ -97,8 +107,8 @@ static void checkDockerAvailability() { socksProxy.start(); LOGGER.info("Dante SOCKS proxy started successfully on port {}", socksProxy.getMappedPort(SOCKS_PORT)); } catch (Exception e) { - LOGGER.warn("Failed to start Dante SOCKS proxy container: {}", e.getMessage()); - dockerAvailable = false; // Mark as unavailable if container start fails + LOGGER.warn("Failed to start test containers: {}", e.getMessage()); + dockerAvailable = false; } } } @@ -108,6 +118,12 @@ static void stopContainer() { if (socksProxy != null && socksProxy.isRunning()) { socksProxy.stop(); } + if (targetServer != null && targetServer.isRunning()) { + targetServer.stop(); + } + if (network != null) { + network.close(); + } } @RepeatedIfExceptionsTest(repeats = 3) @@ -122,9 +138,9 @@ public void testSocks4ProxyToHttpTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTP_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("httpbin")); + assertTrue(response.getResponseBody().contains(LocalProxyTestTarget.BODY_MARKER)); LOGGER.info("SOCKS4 proxy to HTTP target test passed"); } } @@ -141,9 +157,9 @@ public void testSocks5ProxyToHttpTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTP_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("httpbin")); + assertTrue(response.getResponseBody().contains(LocalProxyTestTarget.BODY_MARKER)); LOGGER.info("SOCKS5 proxy to HTTP target test passed"); } } @@ -161,10 +177,9 @@ public void testSocks4ProxyToHttpsTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTPS_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpsUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("Example Domain") || - response.getResponseBody().contains("example")); + assertTrue(response.getResponseBody().contains("AHC Test Target")); LOGGER.info("SOCKS4 proxy to HTTPS target test passed - issue #1913 RESOLVED!"); } } @@ -182,10 +197,9 @@ public void testSocks5ProxyToHttpsTarget() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)) .build(); try (AsyncHttpClient client = asyncHttpClient(config)) { - Response response = client.executeRequest(get(TARGET_HTTPS_URL)).get(30, TimeUnit.SECONDS); + Response response = client.executeRequest(get(targetHttpsUrl)).get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("Example Domain") || - response.getResponseBody().contains("example")); + assertTrue(response.getResponseBody().contains("AHC Test Target")); LOGGER.info("SOCKS5 proxy to HTTPS target test passed - issue #1913 RESOLVED!"); } } @@ -206,10 +220,9 @@ public void testIssue1913ReproductionWithRealProxy() throws Exception { .setRequestTimeout(Duration.ofMillis(30000)))) { // This would previously throw: java.util.NoSuchElementException: socks - var response = client.prepareGet("https://www.example.com/").execute().get(30, TimeUnit.SECONDS); + var response = client.prepareGet(targetHttpsUrl).execute().get(30, TimeUnit.SECONDS); assertEquals(200, response.getStatusCode()); - assertTrue(response.getResponseBody().contains("Example Domain") || - response.getResponseBody().contains("example")); + assertTrue(response.getResponseBody().contains("AHC Test Target")); LOGGER.info("Issue #1913 reproduction test PASSED - NoSuchElementException: socks is FIXED!"); } } diff --git a/client/src/test/java/org/asynchttpclient/testserver/SocksProxy.java b/client/src/test/java/org/asynchttpclient/testserver/SocksProxy.java index b8e67b79f5..5ca15fa288 100644 --- a/client/src/test/java/org/asynchttpclient/testserver/SocksProxy.java +++ b/client/src/test/java/org/asynchttpclient/testserver/SocksProxy.java @@ -7,8 +7,7 @@ package org.asynchttpclient.testserver; -// NOTES : LISTENS ON PORT 8000 - +import java.io.Closeable; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -22,74 +21,109 @@ public class SocksProxy { - private static final ArrayList clients = new ArrayList<>(); + private final ArrayList clients = new ArrayList<>(); + private final ServerSocketChannel socks; + private final Selector select; + private final long runningTime; + private volatile boolean stopped; public SocksProxy(int runningTime) throws IOException { - ServerSocketChannel socks = ServerSocketChannel.open(); - socks.socket().bind(new InetSocketAddress(8000)); + this.runningTime = runningTime; + socks = ServerSocketChannel.open(); + socks.socket().bind(new InetSocketAddress(0)); socks.configureBlocking(false); - Selector select = Selector.open(); + select = Selector.open(); socks.register(select, SelectionKey.OP_ACCEPT); + } - int lastClients = clients.size(); - // select loop - for (long end = System.currentTimeMillis() + runningTime; System.currentTimeMillis() < end; ) { - select.select(5000); + public int getPort() { + return socks.socket().getLocalPort(); + } - Set keys = select.selectedKeys(); - for (SelectionKey k : keys) { + public void stop() { + stopped = true; + select.wakeup(); + } - if (!k.isValid()) { - continue; - } + public void run() throws IOException { + try { + int lastClients = clients.size(); + // select loop + for (long end = System.currentTimeMillis() + runningTime; !stopped && System.currentTimeMillis() < end; ) { + select.select(5000); + + Set keys = select.selectedKeys(); + for (SelectionKey k : keys) { - // new connection? - if (k.isAcceptable() && k.channel() == socks) { - // server socket - SocketChannel csock = socks.accept(); - if (csock == null) { + if (!k.isValid()) { continue; } - addClient(csock); - csock.register(select, SelectionKey.OP_READ); - } else if (k.isReadable()) { - // new data on a client/remote socket - for (int i = 0; i < clients.size(); i++) { - SocksClient cl = clients.get(i); - try { - if (k.channel() == cl.client) // from client (e.g. socks client) - { - cl.newClientData(select); - } else if (k.channel() == cl.remote) { // from server client is connected to (e.g. website) - cl.newRemoteData(); - } - } catch (IOException e) { // error occurred - remove client - cl.client.close(); - if (cl.remote != null) { - cl.remote.close(); - } - k.cancel(); - clients.remove(cl); + + // new connection? + if (k.isAcceptable() && k.channel() == socks) { + // server socket + SocketChannel csock = socks.accept(); + if (csock == null) { + continue; } + addClient(csock); + csock.register(select, SelectionKey.OP_READ); + } else if (k.isReadable()) { + // new data on a client/remote socket + for (int i = 0; i < clients.size(); i++) { + SocksClient cl = clients.get(i); + try { + if (k.channel() == cl.client) // from client (e.g. socks client) + { + cl.newClientData(select); + } else if (k.channel() == cl.remote) { // from server client is connected to (e.g. website) + cl.newRemoteData(); + } + } catch (IOException e) { // error occurred - remove client + cl.client.close(); + if (cl.remote != null) { + cl.remote.close(); + } + k.cancel(); + clients.remove(cl); + } + } } } - } - // client timeout check - for (int i = 0; i < clients.size(); i++) { - SocksClient cl = clients.get(i); - if (System.currentTimeMillis() - cl.lastData > 30000L) { - cl.client.close(); - if (cl.remote != null) { - cl.remote.close(); + // client timeout check + for (int i = 0; i < clients.size(); i++) { + SocksClient cl = clients.get(i); + if (System.currentTimeMillis() - cl.lastData > 30000L) { + cl.client.close(); + if (cl.remote != null) { + cl.remote.close(); + } + clients.remove(cl); } - clients.remove(cl); + } + if (clients.size() != lastClients) { + System.out.println(clients.size()); + lastClients = clients.size(); } } - if (clients.size() != lastClients) { - System.out.println(clients.size()); - lastClients = clients.size(); + } finally { + for (SocksClient cl : clients) { + closeQuietly(cl.client); + closeQuietly(cl.remote); + } + clients.clear(); + closeQuietly(socks); + closeQuietly(select); + } + } + + private static void closeQuietly(Closeable c) { + if (c != null) { + try { + c.close(); + } catch (IOException ignored) { } } } diff --git a/client/src/test/resources/proxy-target/nginx.conf b/client/src/test/resources/proxy-target/nginx.conf new file mode 100644 index 0000000000..a4dd1a8000 --- /dev/null +++ b/client/src/test/resources/proxy-target/nginx.conf @@ -0,0 +1,26 @@ +worker_processes 1; + +events { + worker_connections 64; +} + +http { + server { + listen 80; + listen 443 ssl; + + ssl_certificate /etc/nginx/certs/server.crt; + ssl_certificate_key /etc/nginx/certs/server.key; + + location = /get { + default_type application/json; + return 200 '{"server":"ahc-test-target","path":"/get"}'; + } + + # page used by the *ToHttpsTarget tests + location / { + default_type text/html; + return 200 'AHC Test Target

AHC Test Target

'; + } + } +} diff --git a/client/src/test/resources/proxy-target/server.crt b/client/src/test/resources/proxy-target/server.crt new file mode 100644 index 0000000000..db5af2d256 --- /dev/null +++ b/client/src/test/resources/proxy-target/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFzCCAf+gAwIBAgIUKPcMSYY7IgM39KhRoYUgpYzCj2AwDQYJKoZIhvcNAQEL +BQAwGjEYMBYGA1UEAwwPYWhjLXRlc3QtdGFyZ2V0MCAXDTI2MDcxODIyMjIxMloY +DzIxMjYwNjI0MjIyMjEyWjAaMRgwFgYDVQQDDA9haGMtdGVzdC10YXJnZXQwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKgq4xZzgI6eaWPOq8q+cgSh/B +QaMJT954p/gnq7CjJaHqLyTKSwTOTP7fYcKexl6tGXbW+uFN30ZivrBwgWHdVqm4 +9uFyq2qsPwUucqEv94lKrhiMyDHzYmGIORDyq7cTDtV46CiF6AcKcgQGDQFdovkp +k90VcTeqEzgDt0IXLBCr9NRC4iY7T6zuEVHciIWBChGyff7ykFFHZ/744v+BMflF +Ofy8howBGLGkjCnEYIvV3wZSMFnFrGcTlSQiXT6adcdcELae/GyZZIdfoSGfaxZv +IUMuN+WeV+yAyEOjAfCww6MbY2DBiWxRpgh6lGr6spAQFZBUANFX3UZ96CpxAgMB +AAGjUzBRMB0GA1UdDgQWBBQxbGKPus4aMQuEgepk6T5KFT6J+DAfBgNVHSMEGDAW +gBQxbGKPus4aMQuEgepk6T5KFT6J+DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQA2/MsLGIsY73OzEu0kzJA9BCH8LrGyv8GYY0Lbu92UzGBHAeBU +FYU0l4OhfVbyN/cXPdWoMVadNidNamZV7vLTu3tpxXysXiyCfcrBnp2Bb94WlrAq +mR2PFZtCORoHcZnVIDa6VoHvcYzgkQiPkWXjCUZHJrgCtNBVK4bo4OOTUhJEZ2jD +fR0b/QpzXoT5MQpnL6SuS+bKb7EwLRTwyx+DOe2cVOS5nDeTZMUnjy/sInObErca +FKF+Tp9es6OYBhRuMxaJeOSduGi3rWHqI8xuxOqPI6ZOFH/JzXBZHFD7JVr7crje +1RVywhMXmJhgP7hqMrsdHpkMaSbC6rodvB3F +-----END CERTIFICATE----- diff --git a/client/src/test/resources/proxy-target/server.key b/client/src/test/resources/proxy-target/server.key new file mode 100644 index 0000000000..ce2dffceed --- /dev/null +++ b/client/src/test/resources/proxy-target/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDKgq4xZzgI6eaW +POq8q+cgSh/BQaMJT954p/gnq7CjJaHqLyTKSwTOTP7fYcKexl6tGXbW+uFN30Zi +vrBwgWHdVqm49uFyq2qsPwUucqEv94lKrhiMyDHzYmGIORDyq7cTDtV46CiF6AcK +cgQGDQFdovkpk90VcTeqEzgDt0IXLBCr9NRC4iY7T6zuEVHciIWBChGyff7ykFFH +Z/744v+BMflFOfy8howBGLGkjCnEYIvV3wZSMFnFrGcTlSQiXT6adcdcELae/GyZ +ZIdfoSGfaxZvIUMuN+WeV+yAyEOjAfCww6MbY2DBiWxRpgh6lGr6spAQFZBUANFX +3UZ96CpxAgMBAAECggEALIVeVm4i25LQpubtlF0WivrA0HPlq/5rIouK+u27/6Ie +XqXOqMqlW9WBkwqjBtUFq3iVr92n+r7DcqIJmDJZmZeb6JYeKl+VLBkOwo9g8HKz +ND/iFdFNafyPBKvHFhK6RO5V8CbaAdZo9drrF4l0a2mQ7ZscV8J0QmfHQMnhNcaO +I9/X9z2Rl4nX55p91IRDt1H1uZvkLKj09J05WVa/I3MkkZMAdOEaqQAFzPaaSDWO +SdC2iJJPm2TEP62I54KzPGIlSCz9GZjKyAQEDY7YJeP61ynPfUOWSjPle2uHL53d +gylPkv8MNQwN34KOG3PowEsBUrQcoOzsWtJHjKnwIQKBgQDm6d4Sg/t5U8U2IoQ2 +aR+lTIAFlmN9crUwRzNIEYYXTk6acTlvNTvan68Y9Hgm5z+1aKEY23/Bx1Q+hwpv +YQQR3BuYKIfIocEUZd770HYa8YDdsjVv4rP7nl4iYiaCIVx2hm+TKgtlrQJP/I1Z +8Boan0qSmZgbv1/iBjQJymYnrwKBgQDggt736ybEaNSH05xctlJpvHgwk8JqmsWi +9oBe8U+t4YqsNl937MEbPWcPJY1qORkL4j5ZCxKG+iT+QOPRzhPClC6osUqTwNu/ +GT8cqNgyhHpXhvdc5/XZjPFonxyFd1KEPUEbzmaivIlVRL4JZ+axyuwDMHWB2kBT +ZHLBDis33wKBgFWazeE/XLMWAz6WfT1Oq5S0T6HCpw+Svuku/CvzkyqAtVM8Nnar +3YynNlqiBwklIdE3AMIeXbaRFwI3Pf8ckE2us+ws2mnezZ2qRohEOAS1E3kc4AKi +oObfRzan/G6xv32RSTvdkmwXP4w3rI9zG7pS42qF1oYy5HD+q7wVdNmxAoGAWkLD +OZEEqPosV98vgeabA3+OIpmFFC7dPkM0IPeLPTDr+4hwoVpB2J27DU/fptEFzM1M +m6fj7vgqXz3fWb4sG5JPn+qHPRfQQOf5g6AuK0EvnnjYgjWPlcMgWxt87/uk5R1r +S66TfOGnpOxaKpXnHZujfzTASVBhhCViLVNw9KkCgYBfkjhdSh4a0g4xmthL/1/O +OadEIgJ7NX8W0tPi2p2yESs9mtxwNsuSFmpXXzHaJFCaWJ+OuwMsm/QUXaO3ZHK0 +HoTjq+f64HP1y6rt7Dw/sl2dMa/n+KLz3G0c6EpT2lkKf963/pbQqer4iZUDHYoy +dfRNldANmkGIDMweEW+DFQ== +-----END PRIVATE KEY-----