Skip to content

Commit 6ef7fa6

Browse files
authored
[DE-930] HTTP proxy support (#584)
1 parent d9d8e61 commit 6ef7fa6

File tree

8 files changed

+164
-16
lines changed

8 files changed

+164
-16
lines changed

Diff for: .circleci/config.yml

+6
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ jobs:
170170
docker-img: <<parameters.docker-img>>
171171
topology: <<parameters.topology>>
172172
ssl: <<parameters.ssl>>
173+
- run:
174+
name: Start proxy
175+
command: ./docker/start_proxy.sh
173176
- load_cache
174177
- run:
175178
name: mvn dependency:tree
@@ -235,6 +238,9 @@ jobs:
235238
docker-img: <<parameters.docker-img>>
236239
topology: <<parameters.topology>>
237240
ssl: <<parameters.ssl>>
241+
- run:
242+
name: Start proxy
243+
command: ./docker/start_proxy.sh
238244
- load_cache
239245
- install
240246
- run:

Diff for: docker/start_proxy.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
docker run -d \
4+
-e LOG_LEVEL=Info \
5+
-e AUTH_USER=user \
6+
-e AUTH_PASSWORD=password \
7+
--network=arangodb -p 8888:8888 \
8+
docker.io/kalaksi/tinyproxy:1.7

Diff for: http-protocol/src/main/java/com/arangodb/http/HttpConnection.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private static String getUserAgent() {
8787
return "JavaDriver/" + PackageVersion.VERSION + " (JVM/" + System.getProperty("java.specification.version") + ")";
8888
}
8989

90-
HttpConnection(final ArangoConfig config, final HostDescription host, final Vertx existingVertx) {
90+
HttpConnection(final ArangoConfig config, final HostDescription host, final HttpProtocolConfig protocolConfig) {
9191
super();
9292
Protocol protocol = config.getProtocol();
9393
ContentType contentType = ContentTypeFactory.of(protocol);
@@ -113,9 +113,9 @@ private static String getUserAgent() {
113113
).toHttpAuthorization();
114114

115115
Vertx vertxToUse;
116-
if (existingVertx != null) {
116+
if (protocolConfig.getVertx() != null) {
117117
// reuse existing Vert.x
118-
vertxToUse = existingVertx;
118+
vertxToUse = protocolConfig.getVertx();
119119
// Vert.x will not be closed when connection is closed
120120
vertxToClose = null;
121121
LOGGER.debug("Reusing existing Vert.x instance");
@@ -154,7 +154,8 @@ private static String getUserAgent() {
154154
.setHttp2ClearTextUpgrade(false)
155155
.setProtocolVersion(httpVersion)
156156
.setDefaultHost(host.getHost())
157-
.setDefaultPort(host.getPort());
157+
.setDefaultPort(host.getPort())
158+
.setProxyOptions(protocolConfig.getProxyOptions());
158159

159160
if (compression != Compression.NONE) {
160161
webClientOptions.setTryUseCompression(true);

Diff for: http-protocol/src/main/java/com/arangodb/http/HttpConnectionFactory.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@
3434
public class HttpConnectionFactory implements ConnectionFactory {
3535
private final Logger LOGGER = LoggerFactory.getLogger(HttpConnectionFactory.class);
3636

37-
private final Vertx vertx;
37+
final HttpProtocolConfig protocolConfig;
3838

39-
public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig config) {
40-
HttpProtocolConfig cfg = config != null ? config : HttpProtocolConfig.builder().build();
41-
vertx = cfg.getVertx();
42-
if (vertx == null && !PackageVersion.SHADED && Vertx.currentContext() != null) {
39+
public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig cfg) {
40+
protocolConfig = cfg != null ? cfg : HttpProtocolConfig.builder().build();
41+
if (protocolConfig.getVertx() == null && !PackageVersion.SHADED && Vertx.currentContext() != null) {
4342
LOGGER.warn("Found an existing Vert.x instance, you can reuse it by setting:\n" +
4443
"new ArangoDB.Builder()\n" +
4544
" // ...\n" +
@@ -51,6 +50,6 @@ public HttpConnectionFactory(@UnstableApi final HttpProtocolConfig config) {
5150
@Override
5251
@UnstableApi
5352
public Connection create(@UnstableApi final ArangoConfig config, final HostDescription host) {
54-
return new HttpConnection(config, host, vertx);
53+
return new HttpConnection(config, host, protocolConfig);
5554
}
5655
}

Diff for: http-protocol/src/main/java/com/arangodb/http/HttpProtocolConfig.java

+19-2
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@
22

33
import com.arangodb.config.ProtocolConfig;
44
import io.vertx.core.Vertx;
5+
import io.vertx.core.net.ProxyOptions;
56

67
public final class HttpProtocolConfig implements ProtocolConfig {
78
private final Vertx vertx;
9+
private final ProxyOptions proxyOptions;
810

911
public static Builder builder() {
1012
return new Builder();
1113
}
1214

1315
public static class Builder {
1416
private Vertx vertx;
17+
private ProxyOptions proxyOptions;
1518

1619
private Builder() {
1720
}
@@ -27,16 +30,30 @@ public Builder vertx(Vertx vertx) {
2730
return this;
2831
}
2932

33+
/**
34+
* @param proxyOptions proxy options for HTTP connections
35+
* @return this builder
36+
*/
37+
public Builder proxyOptions(ProxyOptions proxyOptions) {
38+
this.proxyOptions = proxyOptions;
39+
return this;
40+
}
41+
3042
public HttpProtocolConfig build() {
31-
return new HttpProtocolConfig(vertx);
43+
return new HttpProtocolConfig(vertx, proxyOptions);
3244
}
3345
}
3446

35-
private HttpProtocolConfig(Vertx vertx) {
47+
private HttpProtocolConfig(Vertx vertx, ProxyOptions proxyOptions) {
3648
this.vertx = vertx;
49+
this.proxyOptions = proxyOptions;
3750
}
3851

3952
public Vertx getVertx() {
4053
return vertx;
4154
}
55+
56+
public ProxyOptions getProxyOptions() {
57+
return proxyOptions;
58+
}
4259
}

Diff for: test-functional/pom.xml

+15-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
**/SerdeTest.**,
3838
**/SerializableTest.**,
3939
**/JacksonInterferenceTest.**,
40-
**/JacksonRequestContextTest.**
40+
**/JacksonRequestContextTest.**,
41+
**/HttpProxyTest.**
4142
</filesToExclude>
4243
<replacements>
4344
<replacement>
@@ -101,7 +102,19 @@
101102
</property>
102103
</activation>
103104
<properties>
104-
<testSourceDirectory>src/test-ssl/java</testSourceDirectory>
105+
<testSources>src/test-ssl/java</testSources>
106+
</properties>
107+
</profile>
108+
<profile>
109+
<id>no-ssl</id>
110+
<activation>
111+
<property>
112+
<name>ssl</name>
113+
<value>!true</value>
114+
</property>
115+
</activation>
116+
<properties>
117+
<testSources>src/test/java</testSources>
105118
</properties>
106119
</profile>
107120
<profile>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* DISCLAIMER
3+
*
4+
* Copyright 2016 ArangoDB GmbH, Cologne, Germany
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
*/
20+
21+
package com.arangodb;
22+
23+
import com.arangodb.entity.ArangoDBVersion;
24+
import com.arangodb.http.HttpProtocolConfig;
25+
import io.netty.handler.proxy.ProxyConnectException;
26+
import io.vertx.core.net.ProxyOptions;
27+
import io.vertx.core.net.ProxyType;
28+
import org.junit.jupiter.params.ParameterizedTest;
29+
import org.junit.jupiter.params.provider.EnumSource;
30+
31+
import java.util.List;
32+
33+
import static org.assertj.core.api.Assertions.assertThat;
34+
import static org.assertj.core.api.Assertions.catchThrowable;
35+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
36+
37+
38+
/**
39+
* @author Michele Rastelli
40+
*/
41+
class HttpProxyTest extends BaseTest {
42+
43+
@ParameterizedTest
44+
@EnumSource(Protocol.class)
45+
void httpProxy(Protocol protocol) {
46+
assumeTrue(protocol != Protocol.VST);
47+
48+
final ArangoDB arangoDB = new ArangoDB.Builder()
49+
.protocol(protocol)
50+
.host("172.28.0.1", 8529)
51+
.password("test")
52+
.useSsl(true)
53+
.sslContext(createSslContext())
54+
.verifyHost(false)
55+
.protocolConfig(HttpProtocolConfig.builder()
56+
.proxyOptions(new ProxyOptions()
57+
.setType(ProxyType.HTTP)
58+
.setHost("172.28.0.1")
59+
.setPort(8888)
60+
.setUsername("user")
61+
.setPassword("password"))
62+
.build())
63+
.build();
64+
final ArangoDBVersion version = arangoDB.getVersion();
65+
assertThat(version).isNotNull();
66+
}
67+
68+
69+
@ParameterizedTest
70+
@EnumSource(Protocol.class)
71+
void httpProxyWrongPassword(Protocol protocol) {
72+
assumeTrue(protocol != Protocol.VST);
73+
74+
final ArangoDB arangoDB = new ArangoDB.Builder()
75+
.protocol(protocol)
76+
.host("172.28.0.1", 8529)
77+
.password("test")
78+
.useSsl(true)
79+
.sslContext(createSslContext())
80+
.verifyHost(false)
81+
.protocolConfig(HttpProtocolConfig.builder()
82+
.proxyOptions(new ProxyOptions()
83+
.setType(ProxyType.HTTP)
84+
.setHost("172.28.0.1")
85+
.setPort(8888)
86+
.setUsername("user")
87+
.setPassword("wrong"))
88+
.build())
89+
.build();
90+
Throwable thrown = catchThrowable(arangoDB::getVersion);
91+
assertThat(thrown)
92+
.isInstanceOf(ArangoDBException.class)
93+
.hasMessageContaining("Cannot contact any host!")
94+
.cause()
95+
.isInstanceOf(ArangoDBMultipleException.class);
96+
List<Throwable> causes = ((ArangoDBMultipleException) thrown.getCause()).getExceptions();
97+
assertThat(causes).allSatisfy(e -> assertThat(e)
98+
.isInstanceOf(ProxyConnectException.class)
99+
.hasMessageContaining("status: 401 Unauthorized"));
100+
assertThat(version).isNotNull();
101+
}
102+
103+
}

Diff for: test-parent/pom.xml

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<maven.deploy.skip>true</maven.deploy.skip>
2121
<maven.compiler.source>17</maven.compiler.source>
2222
<maven.compiler.target>17</maven.compiler.target>
23+
<testSources>src/test/java</testSources>
2324
<shaded/>
2425
</properties>
2526

@@ -153,7 +154,7 @@
153154
</activation>
154155

155156
<properties>
156-
<testSourceDirectory>src/test/java</testSourceDirectory>
157+
<testSourceDirectory>${testSources}</testSourceDirectory>
157158
<shaded>false</shaded>
158159
</properties>
159160
<dependencies>
@@ -209,7 +210,7 @@
209210
</execution>
210211
</executions>
211212
<configuration>
212-
<basedir>${project.basedir}/src/test/java</basedir>
213+
<basedir>${project.basedir}/${testSources}</basedir>
213214
<filesToInclude>**</filesToInclude>
214215
<outputBasedir>${project.build.directory}/generated-test-sources</outputBasedir>
215216
<outputDir>replacer</outputDir>

0 commit comments

Comments
 (0)