From b304b85c327b5c26977b1973ccf6f339957d2c8c Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 31 Oct 2024 13:50:55 +0100 Subject: [PATCH 1/5] HTTP proxy configuration --- .circleci/config.yml | 3 ++ docker/start_proxy.sh | 3 ++ .../com/arangodb/http/HttpConnection.java | 9 +++--- .../arangodb/http/HttpConnectionFactory.java | 11 ++++---- .../com/arangodb/http/HttpProtocolConfig.java | 21 ++++++++++++-- .../java/com/arangodb/ArangoSslTest.java | 28 +++++++++++++++++++ 6 files changed, 63 insertions(+), 12 deletions(-) create mode 100755 docker/start_proxy.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 34322d23d..995aa4663 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -170,6 +170,9 @@ jobs: docker-img: <> topology: <> ssl: <> + - run: + name: Start proxy + command: ./docker/start_proxy.sh - load_cache - run: name: mvn dependency:tree diff --git a/docker/start_proxy.sh b/docker/start_proxy.sh new file mode 100755 index 000000000..16b90b2df --- /dev/null +++ b/docker/start_proxy.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run -d -e LOG_LEVEL=Info -e AUTH_USER=user -e AUTH_PASSWORD=password -p 8888:8888 docker.io/kalaksi/tinyproxy:1.7 diff --git a/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java b/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java index bb3e0f441..87a47c760 100644 --- a/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java +++ b/http-protocol/src/main/java/com/arangodb/http/HttpConnection.java @@ -87,7 +87,7 @@ private static String getUserAgent() { return "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + System.getProperty("java.specification.version") + ")"; } - HttpConnection(final ArangoConfig config, final HostDescription host, final Vertx existingVertx) { + HttpConnection(final ArangoConfig config, final HostDescription host, final HttpProtocolConfig protocolConfig) { super(); Protocol protocol = config.getProtocol(); ContentType contentType = ContentTypeFactory.of(protocol); @@ -113,9 +113,9 @@ private static String getUserAgent() { ).toHttpAuthorization(); Vertx vertxToUse; - if (existingVertx != null) { + if (protocolConfig.getVertx() != null) { // reuse existing Vert.x - vertxToUse = existingVertx; + vertxToUse = protocolConfig.getVertx(); // Vert.x will not be closed when connection is closed vertxToClose = null; LOGGER.debug("Reusing existing Vert.x instance"); @@ -154,7 +154,8 @@ private static String getUserAgent() { .setHttp2ClearTextUpgrade(false) .setProtocolVersion(httpVersion) .setDefaultHost(host.getHost()) - .setDefaultPort(host.getPort()); + .setDefaultPort(host.getPort()) + .setProxyOptions(protocolConfig.getProxyOptions()); if (compression != Compression.NONE) { webClientOptions.setTryUseCompression(true); diff --git a/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java b/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java index edde3da19..69980aec3 100644 --- a/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java +++ b/http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java @@ -34,12 +34,11 @@ public class HttpConnectionFactory implements ConnectionFactory { private final Logger LOGGER = LoggerFactory.getLogger(HttpConnectionFactory.class); - private final Vertx vertx; + final HttpProtocolConfig protocolConfig; - public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig config) { - HttpProtocolConfig cfg = config != null ? config : HttpProtocolConfig.builder().build(); - vertx = cfg.getVertx(); - if (vertx == null && !PackageVersion.SHADED && Vertx.currentContext() != null) { + public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig cfg) { + protocolConfig = cfg != null ? cfg : HttpProtocolConfig.builder().build(); + if (protocolConfig.getVertx() == null && !PackageVersion.SHADED && Vertx.currentContext() != null) { LOGGER.warn("Found an existing Vert.x instance, you can reuse it by setting:\n" + "new ArangoDB.Builder()\n" + " // ...\n" + @@ -51,6 +50,6 @@ public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig config) { @Override @UnstableApi public Connection create(@UnstableApi final ArangoConfig config, final HostDescription host) { - return new HttpConnection(config, host, vertx); + return new HttpConnection(config, host, protocolConfig); } } diff --git a/http-protocol/src/main/java/com/arangodb/http/HttpProtocolConfig.java b/http-protocol/src/main/java/com/arangodb/http/HttpProtocolConfig.java index 26c47f825..7a62dc505 100644 --- a/http-protocol/src/main/java/com/arangodb/http/HttpProtocolConfig.java +++ b/http-protocol/src/main/java/com/arangodb/http/HttpProtocolConfig.java @@ -2,9 +2,11 @@ import com.arangodb.config.ProtocolConfig; import io.vertx.core.Vertx; +import io.vertx.core.net.ProxyOptions; public final class HttpProtocolConfig implements ProtocolConfig { private final Vertx vertx; + private final ProxyOptions proxyOptions; public static Builder builder() { return new Builder(); @@ -12,6 +14,7 @@ public static Builder builder() { public static class Builder { private Vertx vertx; + private ProxyOptions proxyOptions; private Builder() { } @@ -27,16 +30,30 @@ public Builder vertx(Vertx vertx) { return this; } + /** + * @param proxyOptions proxy options for HTTP connections + * @return this builder + */ + public Builder proxyOptions(ProxyOptions proxyOptions) { + this.proxyOptions = proxyOptions; + return this; + } + public HttpProtocolConfig build() { - return new HttpProtocolConfig(vertx); + return new HttpProtocolConfig(vertx, proxyOptions); } } - private HttpProtocolConfig(Vertx vertx) { + private HttpProtocolConfig(Vertx vertx, ProxyOptions proxyOptions) { this.vertx = vertx; + this.proxyOptions = proxyOptions; } public Vertx getVertx() { return vertx; } + + public ProxyOptions getProxyOptions() { + return proxyOptions; + } } diff --git a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java index 092276a81..7d39b8d47 100644 --- a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java +++ b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java @@ -21,6 +21,9 @@ package com.arangodb; import com.arangodb.entity.ArangoDBVersion; +import com.arangodb.http.HttpProtocolConfig; +import io.vertx.core.net.ProxyOptions; +import io.vertx.core.net.ProxyType; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -38,6 +41,31 @@ */ class ArangoSslTest extends BaseTest { + @ParameterizedTest + @EnumSource(Protocol.class) + void httpProxy(Protocol protocol) { + assumeTrue(protocol != Protocol.VST); + + final ArangoDB arangoDB = new ArangoDB.Builder() + .protocol(protocol) + .host("172.28.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(false) + .protocolConfig(HttpProtocolConfig.builder() + .proxyOptions(new ProxyOptions() + .setType(ProxyType.HTTP) + .setHost("127.0.0.1") + .setPort(8888) + .setUsername("user") + .setPassword("password")) + .build()) + .build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + @ParameterizedTest @EnumSource(Protocol.class) void connect(Protocol protocol) { From 21be25188d7eaf4a8032f4642f0d960048e405a5 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 31 Oct 2024 14:17:51 +0100 Subject: [PATCH 2/5] CI: fix docker port mapping --- docker/start_proxy.sh | 7 ++++++- .../src/test-ssl/java/com/arangodb/ArangoSslTest.java | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docker/start_proxy.sh b/docker/start_proxy.sh index 16b90b2df..23ff4068d 100755 --- a/docker/start_proxy.sh +++ b/docker/start_proxy.sh @@ -1,3 +1,8 @@ #!/bin/bash -docker run -d -e LOG_LEVEL=Info -e AUTH_USER=user -e AUTH_PASSWORD=password -p 8888:8888 docker.io/kalaksi/tinyproxy:1.7 +docker run -d \ + -e LOG_LEVEL=Info \ + -e AUTH_USER=user \ + -e AUTH_PASSWORD=password \ + --network=arangodb --ip=172.28.0.100 \ + docker.io/kalaksi/tinyproxy:1.7 diff --git a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java index 7d39b8d47..fe8b3c9f0 100644 --- a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java +++ b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java @@ -56,7 +56,7 @@ void httpProxy(Protocol protocol) { .protocolConfig(HttpProtocolConfig.builder() .proxyOptions(new ProxyOptions() .setType(ProxyType.HTTP) - .setHost("127.0.0.1") + .setHost("172.28.0.100") .setPort(8888) .setUsername("user") .setPassword("password")) From 7c29d5811c87e4f59a89cffa9495419d32c35962 Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 31 Oct 2024 14:25:45 +0100 Subject: [PATCH 3/5] CI: fix port mapping --- .circleci/config.yml | 3 +++ docker/start_proxy.sh | 2 +- .../src/test-ssl/java/com/arangodb/ArangoSslTest.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 995aa4663..3ad66ad46 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -238,6 +238,9 @@ jobs: docker-img: <> topology: <> ssl: <> + - run: + name: Start proxy + command: ./docker/start_proxy.sh - load_cache - install - run: diff --git a/docker/start_proxy.sh b/docker/start_proxy.sh index 23ff4068d..b4e938684 100755 --- a/docker/start_proxy.sh +++ b/docker/start_proxy.sh @@ -4,5 +4,5 @@ docker run -d \ -e LOG_LEVEL=Info \ -e AUTH_USER=user \ -e AUTH_PASSWORD=password \ - --network=arangodb --ip=172.28.0.100 \ + --network=arangodb -p 8888:8888 \ docker.io/kalaksi/tinyproxy:1.7 diff --git a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java index fe8b3c9f0..02133d45f 100644 --- a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java +++ b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java @@ -56,7 +56,7 @@ void httpProxy(Protocol protocol) { .protocolConfig(HttpProtocolConfig.builder() .proxyOptions(new ProxyOptions() .setType(ProxyType.HTTP) - .setHost("172.28.0.100") + .setHost("172.28.0.1") .setPort(8888) .setUsername("user") .setPassword("password")) From 65eee45012b271cb6b2a34ecf47be4baf46b958b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 31 Oct 2024 20:30:37 +0100 Subject: [PATCH 4/5] CI: test fix --- .../java/com/arangodb/ArangoSslTest.java | 28 ----- .../java/com/arangodb/HttpProxyTest.java | 109 ++++++++++++++++++ 2 files changed, 109 insertions(+), 28 deletions(-) create mode 100644 test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java diff --git a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java index 02133d45f..092276a81 100644 --- a/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java +++ b/test-functional/src/test-ssl/java/com/arangodb/ArangoSslTest.java @@ -21,9 +21,6 @@ package com.arangodb; import com.arangodb.entity.ArangoDBVersion; -import com.arangodb.http.HttpProtocolConfig; -import io.vertx.core.net.ProxyOptions; -import io.vertx.core.net.ProxyType; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -41,31 +38,6 @@ */ class ArangoSslTest extends BaseTest { - @ParameterizedTest - @EnumSource(Protocol.class) - void httpProxy(Protocol protocol) { - assumeTrue(protocol != Protocol.VST); - - final ArangoDB arangoDB = new ArangoDB.Builder() - .protocol(protocol) - .host("172.28.0.1", 8529) - .password("test") - .useSsl(true) - .sslContext(createSslContext()) - .verifyHost(false) - .protocolConfig(HttpProtocolConfig.builder() - .proxyOptions(new ProxyOptions() - .setType(ProxyType.HTTP) - .setHost("172.28.0.1") - .setPort(8888) - .setUsername("user") - .setPassword("password")) - .build()) - .build(); - final ArangoDBVersion version = arangoDB.getVersion(); - assertThat(version).isNotNull(); - } - @ParameterizedTest @EnumSource(Protocol.class) void connect(Protocol protocol) { diff --git a/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java b/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java new file mode 100644 index 000000000..6d54bf4e0 --- /dev/null +++ b/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java @@ -0,0 +1,109 @@ +/* + * DISCLAIMER + * + * Copyright 2016 ArangoDB GmbH, Cologne, Germany + * + * 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. + * + * Copyright holder is ArangoDB GmbH, Cologne, Germany + */ + +package com.arangodb; + +import com.arangodb.entity.ArangoDBVersion; +import com.arangodb.http.HttpProtocolConfig; +import io.netty.handler.proxy.ProxyConnectException; +import io.vertx.core.net.ProxyOptions; +import io.vertx.core.net.ProxyType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + + +/** + * @author Michele Rastelli + */ +class HttpProxyTest extends BaseTest { + + @BeforeEach + void setUp() { + assumeTrue(!PackageVersion.SHADED); + } + + @ParameterizedTest + @EnumSource(Protocol.class) + void httpProxy(Protocol protocol) { + assumeTrue(protocol != Protocol.VST); + + final ArangoDB arangoDB = new ArangoDB.Builder() + .protocol(protocol) + .host("172.28.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(false) + .protocolConfig(HttpProtocolConfig.builder() + .proxyOptions(new ProxyOptions() + .setType(ProxyType.HTTP) + .setHost("172.28.0.1") + .setPort(8888) + .setUsername("user") + .setPassword("password")) + .build()) + .build(); + final ArangoDBVersion version = arangoDB.getVersion(); + assertThat(version).isNotNull(); + } + + + @ParameterizedTest + @EnumSource(Protocol.class) + void httpProxyWrongPassword(Protocol protocol) { + assumeTrue(protocol != Protocol.VST); + + final ArangoDB arangoDB = new ArangoDB.Builder() + .protocol(protocol) + .host("172.28.0.1", 8529) + .password("test") + .useSsl(true) + .sslContext(createSslContext()) + .verifyHost(false) + .protocolConfig(HttpProtocolConfig.builder() + .proxyOptions(new ProxyOptions() + .setType(ProxyType.HTTP) + .setHost("172.28.0.1") + .setPort(8888) + .setUsername("user") + .setPassword("wrong")) + .build()) + .build(); + Throwable thrown = catchThrowable(arangoDB::getVersion); + assertThat(thrown) + .isInstanceOf(ArangoDBException.class) + .hasMessageContaining("Cannot contact any host!") + .cause() + .isInstanceOf(ArangoDBMultipleException.class); + List causes = ((ArangoDBMultipleException) thrown.getCause()).getExceptions(); + assertThat(causes).allSatisfy(e -> assertThat(e) + .isInstanceOf(ProxyConnectException.class) + .hasMessageContaining("status: 401 Unauthorized")); + assertThat(version).isNotNull(); + } + +} From 552308b3fcf381d600faab13fb4f96462f2f413b Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Thu, 31 Oct 2024 21:29:33 +0100 Subject: [PATCH 5/5] CI: test fix --- test-functional/pom.xml | 17 +++++++++++++++-- .../java/com/arangodb/HttpProxyTest.java | 6 ------ test-parent/pom.xml | 5 +++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/test-functional/pom.xml b/test-functional/pom.xml index bb960521d..ebe379394 100644 --- a/test-functional/pom.xml +++ b/test-functional/pom.xml @@ -37,7 +37,8 @@ **/SerdeTest.**, **/SerializableTest.**, **/JacksonInterferenceTest.**, - **/JacksonRequestContextTest.** + **/JacksonRequestContextTest.**, + **/HttpProxyTest.** @@ -101,7 +102,19 @@ - src/test-ssl/java + src/test-ssl/java + + + + no-ssl + + + ssl + !true + + + + src/test/java diff --git a/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java b/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java index 6d54bf4e0..32305f526 100644 --- a/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java +++ b/test-functional/src/test-ssl/java/com/arangodb/HttpProxyTest.java @@ -25,7 +25,6 @@ import io.netty.handler.proxy.ProxyConnectException; import io.vertx.core.net.ProxyOptions; import io.vertx.core.net.ProxyType; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -41,11 +40,6 @@ */ class HttpProxyTest extends BaseTest { - @BeforeEach - void setUp() { - assumeTrue(!PackageVersion.SHADED); - } - @ParameterizedTest @EnumSource(Protocol.class) void httpProxy(Protocol protocol) { diff --git a/test-parent/pom.xml b/test-parent/pom.xml index b6e977667..aae41facc 100644 --- a/test-parent/pom.xml +++ b/test-parent/pom.xml @@ -20,6 +20,7 @@ true 17 17 + src/test/java @@ -153,7 +154,7 @@ - src/test/java + ${testSources} false @@ -209,7 +210,7 @@ - ${project.basedir}/src/test/java + ${project.basedir}/${testSources} ** ${project.build.directory}/generated-test-sources replacer