Skip to content

Commit cc53247

Browse files
feat: Add proxy support (box/box-codegen#830) (#1424)
1 parent ed04407 commit cc53247

File tree

5 files changed

+160
-6
lines changed

5 files changed

+160
-6
lines changed

.codegen.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "engineHash": "dcdff3f", "specHash": "a05e5d7", "version": "0.1.0" }
1+
{ "engineHash": "ee965c4", "specHash": "a05e5d7", "version": "0.1.0" }

docs/Client.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ divided across resource managers.
1717
- [Custom headers](#custom-headers)
1818
- [Custom Base URLs](#custom-base-urls)
1919
- [Interceptors](#interceptors)
20+
- [Use Proxy for API calls](#use-proxy-for-api-calls)
2021

2122
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
2223

@@ -176,3 +177,18 @@ List<Interceptor> interceptors = new ArrayList<>() {
176177
};
177178
BoxClient clientWithInterceptor = client.withInterceptors(interceptors);
178179
```
180+
181+
# Use Proxy for API calls
182+
183+
In order to use a proxy for API calls, calling the `client.withProxy(proxyConfig)` method creates a new client, leaving the original client unmodified, with the username and password being optional. We only support adding proxy for BoxNetworkClient. If you are using your own implementation of NetworkClient, you would need to configure proxy on your own.
184+
185+
**Note:** We are only supporting http/s proxies with basic authentication. NTLM and other authentication methods are not supported.
186+
187+
```java
188+
ProxyConfig proxyConfig = new ProxyConfig("http://127.0.0.1:3128");
189+
newClient = client.withProxy(proxyConfig);
190+
191+
//Using Basic Auth with username and password
192+
ProxyConfig proxyConfig = new ProxyConfig.Builder("http://127.0.0.1:3128").username("username").password("password").build();
193+
newClient = client.withProxy(proxyConfig);
194+
```

src/main/java/com/box/sdkgen/networking/boxnetworkclient/BoxNetworkClient.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,22 @@
1818
import com.box.sdkgen.networking.fetchresponse.FetchResponse;
1919
import com.box.sdkgen.networking.network.NetworkSession;
2020
import com.box.sdkgen.networking.networkclient.NetworkClient;
21+
import com.box.sdkgen.networking.proxyconfig.ProxyConfig;
2122
import com.fasterxml.jackson.databind.JsonNode;
2223
import java.io.IOException;
24+
import java.net.InetSocketAddress;
25+
import java.net.Proxy;
2326
import java.net.URI;
27+
import java.nio.charset.StandardCharsets;
2428
import java.util.Locale;
2529
import java.util.Map;
2630
import java.util.Objects;
31+
import java.util.Optional;
2732
import java.util.TreeMap;
2833
import java.util.concurrent.TimeUnit;
2934
import java.util.stream.Collectors;
3035
import okhttp3.Call;
36+
import okhttp3.Credentials;
3137
import okhttp3.Headers;
3238
import okhttp3.HttpUrl;
3339
import okhttp3.MediaType;
@@ -44,6 +50,8 @@ public class BoxNetworkClient implements NetworkClient {
4450

4551
private static final int BASE_TIMEOUT = 1;
4652
private static final double RANDOM_FACTOR = 0.5;
53+
private static final int DEFAULT_HTTP_PORT = 80;
54+
private static final int DEFAULT_HTTPS_PORT = 443;
4755

4856
protected OkHttpClient httpClient;
4957

@@ -64,6 +72,36 @@ public OkHttpClient getHttpClient() {
6472
return httpClient;
6573
}
6674

75+
public BoxNetworkClient withProxy(ProxyConfig config) {
76+
URI uri = URI.create(config.getUrl());
77+
String host = Objects.requireNonNull(uri.getHost(), "Invalid Proxy URL");
78+
79+
String scheme =
80+
Optional.ofNullable(uri.getScheme())
81+
.filter(schema -> schema.startsWith("http"))
82+
.orElseThrow(() -> new IllegalArgumentException("Invalid Proxy URL: " + uri));
83+
84+
int port =
85+
(uri.getPort() != -1)
86+
? uri.getPort()
87+
: ("https".equalsIgnoreCase(scheme) ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT);
88+
89+
OkHttpClient.Builder clientBuilder =
90+
httpClient
91+
.newBuilder()
92+
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)));
93+
94+
String username = config.getUsername();
95+
String password = config.getPassword();
96+
if (username != null && !username.trim().isEmpty() && password != null) {
97+
String basic = Credentials.basic(username, password, StandardCharsets.UTF_8);
98+
clientBuilder.proxyAuthenticator(
99+
(route, resp) ->
100+
resp.request().newBuilder().header("Proxy-Authorization", basic).build());
101+
}
102+
return new BoxNetworkClient(clientBuilder.build());
103+
}
104+
67105
public FetchResponse fetch(FetchOptions options) {
68106
NetworkSession networkSession =
69107
options.getNetworkSession() == null ? new NetworkSession() : options.getNetworkSession();

src/main/java/com/box/sdkgen/networking/network/NetworkSession.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.box.sdkgen.networking.network;
22

3+
import com.box.sdkgen.box.errors.BoxSDKError;
34
import com.box.sdkgen.internal.logging.DataSanitizer;
45
import com.box.sdkgen.networking.baseurls.BaseUrls;
56
import com.box.sdkgen.networking.boxnetworkclient.BoxNetworkClient;
67
import com.box.sdkgen.networking.interceptors.Interceptor;
78
import com.box.sdkgen.networking.networkclient.NetworkClient;
9+
import com.box.sdkgen.networking.proxyconfig.ProxyConfig;
810
import com.box.sdkgen.networking.retries.BoxRetryStrategy;
911
import com.box.sdkgen.networking.retries.RetryStrategy;
1012
import java.util.ArrayList;
@@ -27,6 +29,8 @@ public class NetworkSession {
2729

2830
protected DataSanitizer dataSanitizer;
2931

32+
protected ProxyConfig proxyConfig;
33+
3034
public NetworkSession() {
3135
networkClient = new BoxNetworkClient();
3236
retryStrategy = new BoxRetryStrategy();
@@ -40,6 +44,7 @@ protected NetworkSession(Builder builder) {
4044
this.interceptors = builder.interceptors;
4145
this.retryStrategy = builder.retryStrategy;
4246
this.dataSanitizer = builder.dataSanitizer;
47+
this.proxyConfig = builder.proxyConfig;
4348
}
4449

4550
public NetworkSession withAdditionalHeaders() {
@@ -56,7 +61,8 @@ public NetworkSession withAdditionalHeaders(Map<String, String> additionalHeader
5661
.interceptors(this.interceptors)
5762
.networkClient(this.networkClient)
5863
.retryStrategy(this.retryStrategy)
59-
.dataSanitizer(dataSanitizer)
64+
.dataSanitizer(this.dataSanitizer)
65+
.proxyConfig(this.proxyConfig)
6066
.build();
6167
}
6268

@@ -67,7 +73,8 @@ public NetworkSession withCustomBaseUrls(BaseUrls baseUrls) {
6773
.interceptors(this.interceptors)
6874
.networkClient(this.networkClient)
6975
.retryStrategy(this.retryStrategy)
70-
.dataSanitizer(dataSanitizer)
76+
.dataSanitizer(this.dataSanitizer)
77+
.proxyConfig(this.proxyConfig)
7178
.build();
7279
}
7380

@@ -81,7 +88,8 @@ public NetworkSession withInterceptors(List<Interceptor> interceptors) {
8188
.interceptors(newInterceptors)
8289
.networkClient(this.networkClient)
8390
.retryStrategy(this.retryStrategy)
84-
.dataSanitizer(dataSanitizer)
91+
.dataSanitizer(this.dataSanitizer)
92+
.proxyConfig(this.proxyConfig)
8593
.build();
8694
}
8795

@@ -92,7 +100,8 @@ public NetworkSession withNetworkClient(NetworkClient networkClient) {
92100
.interceptors(this.interceptors)
93101
.networkClient(networkClient)
94102
.retryStrategy(this.retryStrategy)
95-
.dataSanitizer(dataSanitizer)
103+
.dataSanitizer(this.dataSanitizer)
104+
.proxyConfig(this.proxyConfig)
96105
.build();
97106
}
98107

@@ -103,7 +112,8 @@ public NetworkSession withRetryStrategy(RetryStrategy retryStrategy) {
103112
.interceptors(this.interceptors)
104113
.networkClient(this.networkClient)
105114
.retryStrategy(retryStrategy)
106-
.dataSanitizer(dataSanitizer)
115+
.dataSanitizer(this.dataSanitizer)
116+
.proxyConfig(this.proxyConfig)
107117
.build();
108118
}
109119

@@ -115,6 +125,26 @@ public NetworkSession withDataSanitizer(DataSanitizer dataSanitizer) {
115125
.networkClient(this.networkClient)
116126
.retryStrategy(this.retryStrategy)
117127
.dataSanitizer(dataSanitizer)
128+
.proxyConfig(this.proxyConfig)
129+
.build();
130+
}
131+
132+
public NetworkSession withProxy(ProxyConfig config) {
133+
if (config == null) {
134+
throw new IllegalArgumentException("ProxyConfig cannot be null");
135+
}
136+
if (!(this.networkClient instanceof BoxNetworkClient)) {
137+
throw new BoxSDKError("Proxies are only supported for BoxNetworkClient");
138+
}
139+
BoxNetworkClient newClient = ((BoxNetworkClient) this.networkClient).withProxy(config);
140+
return new Builder()
141+
.additionalHeaders(this.additionalHeaders)
142+
.baseUrls(this.baseUrls)
143+
.interceptors(this.interceptors)
144+
.networkClient(newClient)
145+
.retryStrategy(this.retryStrategy)
146+
.dataSanitizer(this.dataSanitizer)
147+
.proxyConfig(config)
118148
.build();
119149
}
120150

@@ -142,6 +172,10 @@ public DataSanitizer getDataSanitizer() {
142172
return dataSanitizer;
143173
}
144174

175+
public ProxyConfig getProxyConfig() {
176+
return proxyConfig;
177+
}
178+
145179
public static class Builder {
146180

147181
protected Map<String, String> additionalHeaders = new HashMap<>();
@@ -156,6 +190,8 @@ public static class Builder {
156190

157191
protected DataSanitizer dataSanitizer;
158192

193+
protected ProxyConfig proxyConfig;
194+
159195
public Builder() {
160196
networkClient = new BoxNetworkClient();
161197
retryStrategy = new BoxRetryStrategy();
@@ -192,6 +228,11 @@ public Builder dataSanitizer(DataSanitizer dataSanitizer) {
192228
return this;
193229
}
194230

231+
public Builder proxyConfig(ProxyConfig proxyConfig) {
232+
this.proxyConfig = proxyConfig;
233+
return this;
234+
}
235+
195236
public NetworkSession build() {
196237
return new NetworkSession(this);
197238
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.box.sdkgen.networking.proxyconfig;
2+
3+
public class ProxyConfig {
4+
5+
public final String url;
6+
7+
public String username;
8+
9+
public String password;
10+
11+
public ProxyConfig(String url) {
12+
this.url = url;
13+
}
14+
15+
protected ProxyConfig(Builder builder) {
16+
this.url = builder.url;
17+
this.username = builder.username;
18+
this.password = builder.password;
19+
}
20+
21+
public String getUrl() {
22+
return url;
23+
}
24+
25+
public String getUsername() {
26+
return username;
27+
}
28+
29+
public String getPassword() {
30+
return password;
31+
}
32+
33+
public static class Builder {
34+
35+
protected final String url;
36+
37+
protected String username;
38+
39+
protected String password;
40+
41+
public Builder(String url) {
42+
this.url = url;
43+
}
44+
45+
public Builder username(String username) {
46+
this.username = username;
47+
return this;
48+
}
49+
50+
public Builder password(String password) {
51+
this.password = password;
52+
return this;
53+
}
54+
55+
public ProxyConfig build() {
56+
return new ProxyConfig(this);
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)