1
15
16 package software.amazon.awssdk.http.apache;
17
18 import static software.amazon.awssdk.utils.StringUtils.isEmpty;
19
20 import java.net.URI;
21 import java.util.Arrays;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Set;
25 import java.util.stream.Collectors;
26 import software.amazon.awssdk.annotations.SdkPublicApi;
27 import software.amazon.awssdk.utils.ProxySystemSetting;
28 import software.amazon.awssdk.utils.StringUtils;
29 import software.amazon.awssdk.utils.ToString;
30 import software.amazon.awssdk.utils.Validate;
31 import software.amazon.awssdk.utils.builder.CopyableBuilder;
32 import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
33
34
37 @SdkPublicApi
38 public final class ProxyConfiguration implements ToCopyableBuilder<ProxyConfiguration.Builder, ProxyConfiguration> {
39
40 private final URI endpoint;
41 private final String username;
42 private final String password;
43 private final String ntlmDomain;
44 private final String ntlmWorkstation;
45 private final Set<String> nonProxyHosts;
46 private final Boolean preemptiveBasicAuthenticationEnabled;
47 private final Boolean useSystemPropertyValues;
48 private final String host;
49 private final int port;
50 private final String scheme;
51
52
55 private ProxyConfiguration(DefaultClientProxyConfigurationBuilder builder) {
56 this.endpoint = builder.endpoint;
57 this.username = builder.username;
58 this.password = builder.password;
59 this.ntlmDomain = builder.ntlmDomain;
60 this.ntlmWorkstation = builder.ntlmWorkstation;
61 this.nonProxyHosts = builder.nonProxyHosts;
62 this.preemptiveBasicAuthenticationEnabled = builder.preemptiveBasicAuthenticationEnabled == null ? Boolean.FALSE :
63 builder.preemptiveBasicAuthenticationEnabled;
64 this.useSystemPropertyValues = builder.useSystemPropertyValues;
65 this.host = resolveHost();
66 this.port = resolvePort();
67 this.scheme = resolveScheme();
68 }
69
70
74 public String host() {
75 return host;
76 }
77
78
84 public int port() {
85 return port;
86 }
87
88
91 public String scheme() {
92 return scheme;
93 }
94
95
100 public String username() {
101 return resolveValue(username, ProxySystemSetting.PROXY_USERNAME);
102 }
103
104
109 public String password() {
110 return resolveValue(password, ProxySystemSetting.PROXY_PASSWORD);
111 }
112
113
118 public String ntlmDomain() {
119 return ntlmDomain;
120 }
121
122
127 public String ntlmWorkstation() {
128 return ntlmWorkstation;
129 }
130
131
139 public Set<String> nonProxyHosts() {
140 Set<String> hosts = nonProxyHosts == null && useSystemPropertyValues ? parseNonProxyHostsProperty()
141 : nonProxyHosts;
142
143 return Collections.unmodifiableSet(hosts != null ? hosts : Collections.emptySet());
144 }
145
146
151 public Boolean preemptiveBasicAuthenticationEnabled() {
152 return preemptiveBasicAuthenticationEnabled;
153 }
154
155 @Override
156 public Builder toBuilder() {
157 return builder()
158 .endpoint(endpoint)
159 .username(username)
160 .password(password)
161 .ntlmDomain(ntlmDomain)
162 .ntlmWorkstation(ntlmWorkstation)
163 .nonProxyHosts(nonProxyHosts)
164 .preemptiveBasicAuthenticationEnabled(preemptiveBasicAuthenticationEnabled);
165 }
166
167
170 public static Builder builder() {
171 return new DefaultClientProxyConfigurationBuilder();
172 }
173
174 @Override
175 public String toString() {
176 return ToString.builder("ProxyConfiguration")
177 .add("endpoint", endpoint)
178 .add("username", username)
179 .add("ntlmDomain", ntlmDomain)
180 .add("ntlmWorkstation", ntlmWorkstation)
181 .add("nonProxyHosts", nonProxyHosts)
182 .add("preemptiveBasicAuthenticationEnabled", preemptiveBasicAuthenticationEnabled)
183 .build();
184 }
185
186
187 private String resolveHost() {
188 return endpoint != null ? endpoint.getHost()
189 : resolveValue(null, ProxySystemSetting.PROXY_HOST);
190 }
191
192 private int resolvePort() {
193 int port = 0;
194
195 if (endpoint != null) {
196 port = endpoint.getPort();
197 } else if (useSystemPropertyValues) {
198 port = ProxySystemSetting.PROXY_PORT.getStringValue()
199 .map(Integer::parseInt)
200 .orElse(0);
201 }
202
203 return port;
204 }
205
206 public String resolveScheme() {
207 return endpoint != null ? endpoint.getScheme() : null;
208 }
209
210
213 private String resolveValue(String value, ProxySystemSetting systemSetting) {
214 return value == null && useSystemPropertyValues ? systemSetting.getStringValue().orElse(null)
215 : value;
216 }
217
218
222 private Set<String> parseNonProxyHostsProperty() {
223 String nonProxyHosts = ProxySystemSetting.NON_PROXY_HOSTS.getStringValue().orElse(null);
224
225 if (!StringUtils.isEmpty(nonProxyHosts)) {
226 return Arrays.stream(nonProxyHosts.split("\\|"))
227 .map(String::toLowerCase)
228 .map(s -> s.replace("*", ".*?"))
229 .collect(Collectors.toSet());
230 }
231 return Collections.emptySet();
232 }
233
234
239 public interface Builder extends CopyableBuilder<Builder, ProxyConfiguration> {
240
241
245 Builder endpoint(URI endpoint);
246
247
250 Builder username(String username);
251
252
255 Builder password(String password);
256
257
260 Builder ntlmDomain(String proxyDomain);
261
262
265 Builder ntlmWorkstation(String proxyWorkstation);
266
267
270 Builder nonProxyHosts(Set<String> nonProxyHosts);
271
272
277 Builder addNonProxyHost(String nonProxyHost);
278
279
282 Builder preemptiveBasicAuthenticationEnabled(Boolean preemptiveBasicAuthenticationEnabled);
283
284
291 Builder useSystemPropertyValues(Boolean useSystemPropertyValues);
292
293 }
294
295
298 private static final class DefaultClientProxyConfigurationBuilder implements Builder {
299
300 private URI endpoint;
301 private String username;
302 private String password;
303 private String ntlmDomain;
304 private String ntlmWorkstation;
305 private Set<String> nonProxyHosts;
306 private Boolean preemptiveBasicAuthenticationEnabled;
307 private Boolean useSystemPropertyValues = Boolean.TRUE;
308
309 @Override
310 public Builder endpoint(URI endpoint) {
311 if (endpoint != null) {
312 Validate.isTrue(isEmpty(endpoint.getUserInfo()), "Proxy endpoint user info is not supported.");
313 Validate.isTrue(isEmpty(endpoint.getPath()), "Proxy endpoint path is not supported.");
314 Validate.isTrue(isEmpty(endpoint.getQuery()), "Proxy endpoint query is not supported.");
315 Validate.isTrue(isEmpty(endpoint.getFragment()), "Proxy endpoint fragment is not supported.");
316 }
317
318 this.endpoint = endpoint;
319 return this;
320 }
321
322 public void setEndpoint(URI endpoint) {
323 endpoint(endpoint);
324 }
325
326 @Override
327 public Builder username(String username) {
328 this.username = username;
329 return this;
330 }
331
332 public void setUsername(String username) {
333 username(username);
334 }
335
336 @Override
337 public Builder password(String password) {
338 this.password = password;
339 return this;
340 }
341
342 public void setPassword(String password) {
343 password(password);
344 }
345
346 @Override
347 public Builder ntlmDomain(String proxyDomain) {
348 this.ntlmDomain = proxyDomain;
349 return this;
350 }
351
352 public void setNtlmDomain(String ntlmDomain) {
353 ntlmDomain(ntlmDomain);
354 }
355
356 @Override
357 public Builder ntlmWorkstation(String proxyWorkstation) {
358 this.ntlmWorkstation = proxyWorkstation;
359 return this;
360 }
361
362 public void setNtlmWorkstation(String ntlmWorkstation) {
363 ntlmWorkstation(ntlmWorkstation);
364 }
365
366 @Override
367 public Builder nonProxyHosts(Set<String> nonProxyHosts) {
368 this.nonProxyHosts = new HashSet<>(nonProxyHosts);
369 return this;
370 }
371
372 @Override
373 public Builder addNonProxyHost(String nonProxyHost) {
374 if (this.nonProxyHosts == null) {
375 this.nonProxyHosts = new HashSet<>();
376 }
377 this.nonProxyHosts.add(nonProxyHost);
378 return this;
379 }
380
381 public void setNonProxyHosts(Set<String> nonProxyHosts) {
382 nonProxyHosts(nonProxyHosts);
383 }
384
385 @Override
386 public Builder preemptiveBasicAuthenticationEnabled(Boolean preemptiveBasicAuthenticationEnabled) {
387 this.preemptiveBasicAuthenticationEnabled = preemptiveBasicAuthenticationEnabled;
388 return this;
389 }
390
391 public void setPreemptiveBasicAuthenticationEnabled(Boolean preemptiveBasicAuthenticationEnabled) {
392 preemptiveBasicAuthenticationEnabled(preemptiveBasicAuthenticationEnabled);
393 }
394
395 @Override
396 public Builder useSystemPropertyValues(Boolean useSystemPropertyValues) {
397 this.useSystemPropertyValues = useSystemPropertyValues;
398 return this;
399 }
400
401 public void setUseSystemPropertyValues(Boolean useSystemPropertyValues) {
402 useSystemPropertyValues(useSystemPropertyValues);
403 }
404
405 @Override
406 public ProxyConfiguration build() {
407 return new ProxyConfiguration(this);
408 }
409 }
410 }
411