0
# Proxy Configuration
1
2
The proxy configuration capability provides comprehensive proxy support including HTTP, SOCKS4, and SOCKS5 proxies with authentication, per-destination configuration, and automatic proxy selection based on target addresses.
3
4
## ProxyConfiguration Class
5
6
The central proxy configuration management system.
7
8
```java { .api }
9
public class ProxyConfiguration {
10
public ProxyConfiguration();
11
12
// Proxy management
13
public void addProxy(Proxy proxy);
14
public boolean removeProxy(Proxy proxy);
15
public List<Proxy> getProxies();
16
17
// Proxy selection
18
public Proxy match(Origin origin);
19
20
// Nested Proxy base class
21
public static abstract class Proxy {
22
public Proxy(Origin.Address address, boolean secure);
23
public Proxy(Origin.Address address, boolean secure, Set<String> includedAddresses, Set<String> excludedAddresses);
24
25
public Origin.Address getAddress();
26
public boolean isSecure();
27
public Set<String> getIncludedAddresses();
28
public Set<String> getExcludedAddresses();
29
public URI getURI();
30
31
public boolean matches(Origin origin);
32
33
// Factory methods
34
public static Proxy create(String host, int port);
35
public static Proxy create(String host, int port, boolean secure);
36
public static Proxy create(Origin.Address address, boolean secure);
37
}
38
}
39
```
40
41
## HTTP Proxy
42
43
Standard HTTP proxy configuration for HTTP and HTTPS connections.
44
45
### HttpProxy Class
46
47
```java { .api }
48
public class HttpProxy extends ProxyConfiguration.Proxy {
49
public HttpProxy(String host, int port);
50
public HttpProxy(Origin.Address address, boolean secure);
51
public HttpProxy(Origin.Address address, boolean secure, Set<String> includedAddresses, Set<String> excludedAddresses);
52
}
53
```
54
55
### Usage Examples
56
57
```java
58
// Basic HTTP proxy
59
HttpProxy httpProxy = new HttpProxy("proxy.company.com", 8080);
60
client.getProxyConfiguration().addProxy(httpProxy);
61
62
// HTTPS proxy (secure proxy connection)
63
HttpProxy httpsProxy = new HttpProxy("secure-proxy.company.com", 8443);
64
client.getProxyConfiguration().addProxy(httpsProxy);
65
66
// HTTP proxy with address restrictions
67
Set<String> includedHosts = Set.of("*.example.com", "api.partner.com");
68
Set<String> excludedHosts = Set.of("localhost", "127.0.0.1", "*.internal.com");
69
70
HttpProxy restrictedProxy = new HttpProxy(
71
new Origin.Address("proxy.company.com", 8080),
72
false, // not secure
73
includedHosts,
74
excludedHosts
75
);
76
77
client.getProxyConfiguration().addProxy(restrictedProxy);
78
79
// Make request through proxy
80
ContentResponse response = client.GET("https://external-api.example.com/data");
81
```
82
83
### HTTP Proxy with Authentication
84
85
```java
86
// Configure HTTP proxy
87
HttpProxy proxy = new HttpProxy("authenticated-proxy.company.com", 8080);
88
client.getProxyConfiguration().addProxy(proxy);
89
90
// Add proxy authentication
91
URI proxyUri = URI.create("http://authenticated-proxy.company.com:8080");
92
BasicAuthentication proxyAuth = new BasicAuthentication(proxyUri, "Proxy", "proxyuser", "proxypass");
93
client.getAuthenticationStore().addAuthentication(proxyAuth);
94
95
// Requests will automatically use proxy with authentication
96
ContentResponse response = client.GET("https://api.example.com/data");
97
```
98
99
## SOCKS Proxies
100
101
Support for SOCKS4 and SOCKS5 proxy protocols.
102
103
### Socks4Proxy Class
104
105
```java { .api }
106
public class Socks4Proxy extends ProxyConfiguration.Proxy {
107
public Socks4Proxy(String host, int port);
108
public Socks4Proxy(Origin.Address address, boolean secure);
109
}
110
```
111
112
### Socks5Proxy Class
113
114
```java { .api }
115
public class Socks5Proxy extends ProxyConfiguration.Proxy {
116
public Socks5Proxy(String host, int port);
117
public Socks5Proxy(Origin.Address address, boolean secure);
118
}
119
```
120
121
### Usage Examples
122
123
```java
124
// SOCKS4 proxy
125
Socks4Proxy socks4Proxy = new Socks4Proxy("socks4.proxy.com", 1080);
126
client.getProxyConfiguration().addProxy(socks4Proxy);
127
128
// SOCKS5 proxy
129
Socks5Proxy socks5Proxy = new Socks5Proxy("socks5.proxy.com", 1080);
130
client.getProxyConfiguration().addProxy(socks5Proxy);
131
132
// SOCKS5 proxy with authentication
133
Socks5Proxy authSocks5 = new Socks5Proxy("auth-socks5.proxy.com", 1080);
134
client.getProxyConfiguration().addProxy(authSocks5);
135
136
// Add SOCKS authentication (username/password)
137
URI socksUri = URI.create("socks5://auth-socks5.proxy.com:1080");
138
BasicAuthentication socksAuth = new BasicAuthentication(socksUri, null, "socksuser", "sockspass");
139
client.getAuthenticationStore().addAuthentication(socksAuth);
140
141
// Make request through SOCKS proxy
142
ContentResponse response = client.GET("https://restricted.example.com/data");
143
```
144
145
## Multiple Proxy Configuration
146
147
Configure multiple proxies with automatic selection based on target addresses.
148
149
### Proxy Selection Logic
150
151
```java
152
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
153
154
// Corporate HTTP proxy for internal services
155
Set<String> internalHosts = Set.of("*.company.com", "*.internal.net");
156
HttpProxy corporateProxy = new HttpProxy(
157
new Origin.Address("internal-proxy.company.com", 8080),
158
false,
159
internalHosts,
160
Collections.emptySet()
161
);
162
proxyConfig.addProxy(corporateProxy);
163
164
// SOCKS proxy for external services
165
Set<String> externalHosts = Set.of("*");
166
Set<String> excludeInternal = Set.of("*.company.com", "*.internal.net", "localhost", "127.0.0.1");
167
Socks5Proxy externalProxy = new Socks5Proxy(
168
new Origin.Address("external-socks.company.com", 1080),
169
false
170
);
171
// Configure exclusions for external proxy
172
HttpProxy externalHttpProxy = new HttpProxy(
173
new Origin.Address("external-socks.company.com", 1080),
174
false,
175
externalHosts,
176
excludeInternal
177
);
178
proxyConfig.addProxy(externalHttpProxy);
179
180
// Direct connection for local services
181
Set<String> directHosts = Set.of("localhost", "127.0.0.1", "*.local");
182
// No proxy needed - requests to these hosts will bypass proxy
183
```
184
185
### Conditional Proxy Usage
186
187
```java
188
public class ConditionalProxyClient {
189
private final HttpClient client;
190
private final ProxyConfiguration originalProxyConfig;
191
192
public ConditionalProxyClient() throws Exception {
193
this.client = new HttpClient();
194
this.originalProxyConfig = client.getProxyConfiguration();
195
client.start();
196
}
197
198
public ContentResponse requestWithProxy(String url, ProxyConfiguration.Proxy proxy) throws Exception {
199
ProxyConfiguration tempConfig = new ProxyConfiguration();
200
tempConfig.addProxy(proxy);
201
202
// Temporarily use specific proxy
203
ProxyConfiguration originalConfig = client.getProxyConfiguration();
204
205
try {
206
// Note: In actual usage, you'd need to create a new client with the proxy
207
// as proxy configuration is typically set at client creation time
208
return client.GET(url);
209
} finally {
210
// Restore original configuration
211
}
212
}
213
214
public ContentResponse requestDirect(String url) throws Exception {
215
// Remove all proxies for direct connection
216
ProxyConfiguration noProxyConfig = new ProxyConfiguration();
217
218
// Create temporary client without proxy
219
HttpClient directClient = new HttpClient();
220
directClient.start();
221
222
try {
223
return directClient.GET(url);
224
} finally {
225
directClient.stop();
226
}
227
}
228
}
229
```
230
231
## Proxy Authentication
232
233
Configure authentication for proxy servers.
234
235
### Basic Proxy Authentication
236
237
```java
238
// HTTP proxy with basic authentication
239
HttpProxy proxy = new HttpProxy("auth-proxy.company.com", 8080);
240
client.getProxyConfiguration().addProxy(proxy);
241
242
// Add proxy authentication
243
URI proxyUri = URI.create("http://auth-proxy.company.com:8080");
244
BasicAuthentication proxyAuth = new BasicAuthentication(
245
proxyUri,
246
"Corporate Proxy",
247
"domain\\username",
248
"password"
249
);
250
client.getAuthenticationStore().addAuthentication(proxyAuth);
251
```
252
253
### NTLM Proxy Authentication
254
255
```java
256
// For NTLM authentication, you may need custom authentication implementation
257
public class NTLMProxyAuthentication implements Authentication {
258
private final URI proxyUri;
259
private final String domain;
260
private final String username;
261
private final String password;
262
263
public NTLMProxyAuthentication(URI proxyUri, String domain, String username, String password) {
264
this.proxyUri = proxyUri;
265
this.domain = domain;
266
this.username = username;
267
this.password = password;
268
}
269
270
@Override
271
public String getType() {
272
return "NTLM";
273
}
274
275
@Override
276
public boolean matches(String type, URI uri, String realm) {
277
return "NTLM".equalsIgnoreCase(type) && proxyUri.equals(uri);
278
}
279
280
@Override
281
public AuthenticationResult authenticate(Request request, ContentResponse response,
282
HeaderInfo headerInfo, Context context) {
283
// Implement NTLM authentication logic
284
// This typically involves multiple challenge/response exchanges
285
String ntlmMessage = createNTLMResponse(headerInfo.getParameters());
286
return AuthenticationResult.from(context.getURI(), context.getRealm(), "Proxy-Authorization", ntlmMessage);
287
}
288
289
private String createNTLMResponse(Map<String, String> challenge) {
290
// Implement NTLM message creation
291
// This would typically use a library like JCIFS
292
return "NTLM " + base64EncodedNTLMMessage;
293
}
294
}
295
```
296
297
## Advanced Proxy Configuration
298
299
### Dynamic Proxy Selection
300
301
```java
302
public class DynamicProxySelector {
303
private final List<ProxyConfiguration.Proxy> proxies;
304
private final Map<String, ProxyConfiguration.Proxy> domainProxies;
305
306
public DynamicProxySelector() {
307
this.proxies = new ArrayList<>();
308
this.domainProxies = new HashMap<>();
309
310
// Configure domain-specific proxies
311
domainProxies.put("api.partner1.com", new HttpProxy("partner1-proxy.com", 8080));
312
domainProxies.put("api.partner2.com", new Socks5Proxy("partner2-socks.com", 1080));
313
314
// Default corporate proxy
315
proxies.add(new HttpProxy("corporate-proxy.company.com", 8080));
316
}
317
318
public ProxyConfiguration.Proxy selectProxy(URI uri) {
319
String host = uri.getHost();
320
321
// Check for domain-specific proxy
322
ProxyConfiguration.Proxy domainProxy = domainProxies.get(host);
323
if (domainProxy != null) {
324
return domainProxy;
325
}
326
327
// Check for wildcard domain matches
328
for (Map.Entry<String, ProxyConfiguration.Proxy> entry : domainProxies.entrySet()) {
329
if (host.endsWith(entry.getKey().substring(1))) { // Remove * from *.domain.com
330
return entry.getValue();
331
}
332
}
333
334
// Return default proxy
335
return proxies.get(0);
336
}
337
}
338
```
339
340
### Proxy Health Checking
341
342
```java
343
public class ProxyHealthChecker {
344
private final HttpClient testClient;
345
private final Map<ProxyConfiguration.Proxy, Boolean> proxyHealth;
346
347
public ProxyHealthChecker() throws Exception {
348
this.testClient = new HttpClient();
349
this.testClient.setConnectTimeout(5000);
350
this.testClient.setIdleTimeout(10000);
351
this.testClient.start();
352
this.proxyHealth = new ConcurrentHashMap<>();
353
}
354
355
public boolean isProxyHealthy(ProxyConfiguration.Proxy proxy) {
356
return proxyHealth.computeIfAbsent(proxy, this::checkProxyHealth);
357
}
358
359
private boolean checkProxyHealth(ProxyConfiguration.Proxy proxy) {
360
try {
361
// Create temporary client with this proxy
362
HttpClient proxyTestClient = new HttpClient();
363
ProxyConfiguration testProxyConfig = new ProxyConfiguration();
364
testProxyConfig.addProxy(proxy);
365
// Set proxy configuration on test client
366
367
proxyTestClient.start();
368
369
try {
370
// Test proxy with a simple request
371
ContentResponse response = proxyTestClient.GET("http://httpbin.org/ip");
372
return response.getStatus() == 200;
373
} finally {
374
proxyTestClient.stop();
375
}
376
} catch (Exception e) {
377
return false;
378
}
379
}
380
381
public void scheduleHealthChecks(ScheduledExecutorService scheduler) {
382
scheduler.scheduleAtFixedRate(() -> {
383
proxyHealth.keySet().forEach(proxy -> {
384
boolean healthy = checkProxyHealth(proxy);
385
proxyHealth.put(proxy, healthy);
386
if (!healthy) {
387
System.err.println("Proxy unhealthy: " + proxy.getAddress());
388
}
389
});
390
}, 0, 60, TimeUnit.SECONDS);
391
}
392
}
393
```
394
395
## Proxy Bypass and Direct Connections
396
397
Configure proxy bypass for specific destinations.
398
399
### No Proxy Configuration
400
401
```java
402
// Configure proxy but exclude certain hosts
403
Set<String> noProxyHosts = Set.of(
404
"localhost",
405
"127.0.0.1",
406
"*.local",
407
"*.company.com",
408
"internal-api.example.com"
409
);
410
411
HttpProxy proxy = new HttpProxy(
412
new Origin.Address("proxy.company.com", 8080),
413
false,
414
Collections.singleton("*"), // Include all hosts by default
415
noProxyHosts // Exclude these hosts from proxy
416
);
417
418
client.getProxyConfiguration().addProxy(proxy);
419
420
// Requests to excluded hosts will bypass proxy
421
ContentResponse directResponse = client.GET("https://internal-api.company.com/data");
422
ContentResponse proxiedResponse = client.GET("https://external-api.example.com/data");
423
```
424
425
### Environment-Based Proxy Configuration
426
427
```java
428
public class EnvironmentProxyConfig {
429
public static void configureFromEnvironment(HttpClient client) {
430
// Read proxy configuration from environment variables
431
String httpProxy = System.getenv("HTTP_PROXY");
432
String httpsProxy = System.getenv("HTTPS_PROXY");
433
String noProxy = System.getenv("NO_PROXY");
434
435
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
436
437
if (httpProxy != null) {
438
URI proxyUri = URI.create(httpProxy);
439
HttpProxy proxy = new HttpProxy(proxyUri.getHost(), proxyUri.getPort());
440
441
// Configure no-proxy hosts if specified
442
if (noProxy != null) {
443
Set<String> noProxyHosts = Set.of(noProxy.split(","));
444
proxy = new HttpProxy(
445
new Origin.Address(proxyUri.getHost(), proxyUri.getPort()),
446
false,
447
Collections.singleton("*"),
448
noProxyHosts
449
);
450
}
451
452
proxyConfig.addProxy(proxy);
453
454
// Configure proxy authentication if present in URI
455
String userInfo = proxyUri.getUserInfo();
456
if (userInfo != null) {
457
String[] credentials = userInfo.split(":");
458
if (credentials.length == 2) {
459
BasicAuthentication proxyAuth = new BasicAuthentication(
460
proxyUri,
461
null,
462
credentials[0],
463
credentials[1]
464
);
465
client.getAuthenticationStore().addAuthentication(proxyAuth);
466
}
467
}
468
}
469
}
470
}
471
472
// Usage
473
EnvironmentProxyConfig.configureFromEnvironment(client);
474
```
475
476
## Troubleshooting Proxy Issues
477
478
### Proxy Connection Debugging
479
480
```java
481
public class ProxyDebugger {
482
public static void debugProxyConnection(HttpClient client, String testUrl) {
483
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
484
485
System.out.println("Configured proxies:");
486
for (ProxyConfiguration.Proxy proxy : proxyConfig.getProxies()) {
487
System.out.println(" " + proxy.getClass().getSimpleName() +
488
" - " + proxy.getAddress() +
489
" (secure: " + proxy.isSecure() + ")");
490
System.out.println(" Included: " + proxy.getIncludedAddresses());
491
System.out.println(" Excluded: " + proxy.getExcludedAddresses());
492
}
493
494
// Test proxy selection for target URL
495
try {
496
URI uri = URI.create(testUrl);
497
Origin origin = new Origin("https", uri.getHost(), uri.getPort());
498
ProxyConfiguration.Proxy selectedProxy = proxyConfig.match(origin);
499
500
if (selectedProxy != null) {
501
System.out.println("Selected proxy for " + testUrl + ": " + selectedProxy.getAddress());
502
} else {
503
System.out.println("No proxy selected for " + testUrl + " (direct connection)");
504
}
505
} catch (Exception e) {
506
System.err.println("Error testing proxy selection: " + e.getMessage());
507
}
508
}
509
}
510
```
511
512
### Proxy Error Handling
513
514
```java
515
client.newRequest("https://api.example.com/data")
516
.send(result -> {
517
if (result.isFailed()) {
518
Throwable failure = result.getFailure();
519
520
if (failure instanceof ConnectException) {
521
System.err.println("Failed to connect to proxy server");
522
} else if (failure instanceof HttpRequestException) {
523
HttpRequestException httpEx = (HttpRequestException) failure;
524
System.err.println("Proxy request failed: " + httpEx.getMessage());
525
} else if (failure.getMessage().contains("407")) {
526
System.err.println("Proxy authentication required");
527
} else {
528
System.err.println("Proxy-related error: " + failure.getMessage());
529
}
530
}
531
});
532
```