Eclipse Jetty HTTP Client - A lightweight, asynchronous HTTP client library that supports HTTP/1.1, HTTP/2, WebSocket, and various authentication mechanisms, proxy configurations, and connection pooling strategies.
—
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.
The central proxy configuration management system.
public class ProxyConfiguration {
public ProxyConfiguration();
// Proxy management
public void addProxy(Proxy proxy);
public boolean removeProxy(Proxy proxy);
public List<Proxy> getProxies();
// Proxy selection
public Proxy match(Origin origin);
// Nested Proxy base class
public static abstract class Proxy {
public Proxy(Origin.Address address, boolean secure);
public Proxy(Origin.Address address, boolean secure, Set<String> includedAddresses, Set<String> excludedAddresses);
public Origin.Address getAddress();
public boolean isSecure();
public Set<String> getIncludedAddresses();
public Set<String> getExcludedAddresses();
public URI getURI();
public boolean matches(Origin origin);
// Factory methods
public static Proxy create(String host, int port);
public static Proxy create(String host, int port, boolean secure);
public static Proxy create(Origin.Address address, boolean secure);
}
}Standard HTTP proxy configuration for HTTP and HTTPS connections.
public class HttpProxy extends ProxyConfiguration.Proxy {
public HttpProxy(String host, int port);
public HttpProxy(Origin.Address address, boolean secure);
public HttpProxy(Origin.Address address, boolean secure, Set<String> includedAddresses, Set<String> excludedAddresses);
}// Basic HTTP proxy
HttpProxy httpProxy = new HttpProxy("proxy.company.com", 8080);
client.getProxyConfiguration().addProxy(httpProxy);
// HTTPS proxy (secure proxy connection)
HttpProxy httpsProxy = new HttpProxy("secure-proxy.company.com", 8443);
client.getProxyConfiguration().addProxy(httpsProxy);
// HTTP proxy with address restrictions
Set<String> includedHosts = Set.of("*.example.com", "api.partner.com");
Set<String> excludedHosts = Set.of("localhost", "127.0.0.1", "*.internal.com");
HttpProxy restrictedProxy = new HttpProxy(
new Origin.Address("proxy.company.com", 8080),
false, // not secure
includedHosts,
excludedHosts
);
client.getProxyConfiguration().addProxy(restrictedProxy);
// Make request through proxy
ContentResponse response = client.GET("https://external-api.example.com/data");// Configure HTTP proxy
HttpProxy proxy = new HttpProxy("authenticated-proxy.company.com", 8080);
client.getProxyConfiguration().addProxy(proxy);
// Add proxy authentication
URI proxyUri = URI.create("http://authenticated-proxy.company.com:8080");
BasicAuthentication proxyAuth = new BasicAuthentication(proxyUri, "Proxy", "proxyuser", "proxypass");
client.getAuthenticationStore().addAuthentication(proxyAuth);
// Requests will automatically use proxy with authentication
ContentResponse response = client.GET("https://api.example.com/data");Support for SOCKS4 and SOCKS5 proxy protocols.
public class Socks4Proxy extends ProxyConfiguration.Proxy {
public Socks4Proxy(String host, int port);
public Socks4Proxy(Origin.Address address, boolean secure);
}public class Socks5Proxy extends ProxyConfiguration.Proxy {
public Socks5Proxy(String host, int port);
public Socks5Proxy(Origin.Address address, boolean secure);
}// SOCKS4 proxy
Socks4Proxy socks4Proxy = new Socks4Proxy("socks4.proxy.com", 1080);
client.getProxyConfiguration().addProxy(socks4Proxy);
// SOCKS5 proxy
Socks5Proxy socks5Proxy = new Socks5Proxy("socks5.proxy.com", 1080);
client.getProxyConfiguration().addProxy(socks5Proxy);
// SOCKS5 proxy with authentication
Socks5Proxy authSocks5 = new Socks5Proxy("auth-socks5.proxy.com", 1080);
client.getProxyConfiguration().addProxy(authSocks5);
// Add SOCKS authentication (username/password)
URI socksUri = URI.create("socks5://auth-socks5.proxy.com:1080");
BasicAuthentication socksAuth = new BasicAuthentication(socksUri, null, "socksuser", "sockspass");
client.getAuthenticationStore().addAuthentication(socksAuth);
// Make request through SOCKS proxy
ContentResponse response = client.GET("https://restricted.example.com/data");Configure multiple proxies with automatic selection based on target addresses.
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
// Corporate HTTP proxy for internal services
Set<String> internalHosts = Set.of("*.company.com", "*.internal.net");
HttpProxy corporateProxy = new HttpProxy(
new Origin.Address("internal-proxy.company.com", 8080),
false,
internalHosts,
Collections.emptySet()
);
proxyConfig.addProxy(corporateProxy);
// SOCKS proxy for external services
Set<String> externalHosts = Set.of("*");
Set<String> excludeInternal = Set.of("*.company.com", "*.internal.net", "localhost", "127.0.0.1");
Socks5Proxy externalProxy = new Socks5Proxy(
new Origin.Address("external-socks.company.com", 1080),
false
);
// Configure exclusions for external proxy
HttpProxy externalHttpProxy = new HttpProxy(
new Origin.Address("external-socks.company.com", 1080),
false,
externalHosts,
excludeInternal
);
proxyConfig.addProxy(externalHttpProxy);
// Direct connection for local services
Set<String> directHosts = Set.of("localhost", "127.0.0.1", "*.local");
// No proxy needed - requests to these hosts will bypass proxypublic class ConditionalProxyClient {
private final HttpClient client;
private final ProxyConfiguration originalProxyConfig;
public ConditionalProxyClient() throws Exception {
this.client = new HttpClient();
this.originalProxyConfig = client.getProxyConfiguration();
client.start();
}
public ContentResponse requestWithProxy(String url, ProxyConfiguration.Proxy proxy) throws Exception {
ProxyConfiguration tempConfig = new ProxyConfiguration();
tempConfig.addProxy(proxy);
// Temporarily use specific proxy
ProxyConfiguration originalConfig = client.getProxyConfiguration();
try {
// Note: In actual usage, you'd need to create a new client with the proxy
// as proxy configuration is typically set at client creation time
return client.GET(url);
} finally {
// Restore original configuration
}
}
public ContentResponse requestDirect(String url) throws Exception {
// Remove all proxies for direct connection
ProxyConfiguration noProxyConfig = new ProxyConfiguration();
// Create temporary client without proxy
HttpClient directClient = new HttpClient();
directClient.start();
try {
return directClient.GET(url);
} finally {
directClient.stop();
}
}
}Configure authentication for proxy servers.
// HTTP proxy with basic authentication
HttpProxy proxy = new HttpProxy("auth-proxy.company.com", 8080);
client.getProxyConfiguration().addProxy(proxy);
// Add proxy authentication
URI proxyUri = URI.create("http://auth-proxy.company.com:8080");
BasicAuthentication proxyAuth = new BasicAuthentication(
proxyUri,
"Corporate Proxy",
"domain\\username",
"password"
);
client.getAuthenticationStore().addAuthentication(proxyAuth);// For NTLM authentication, you may need custom authentication implementation
public class NTLMProxyAuthentication implements Authentication {
private final URI proxyUri;
private final String domain;
private final String username;
private final String password;
public NTLMProxyAuthentication(URI proxyUri, String domain, String username, String password) {
this.proxyUri = proxyUri;
this.domain = domain;
this.username = username;
this.password = password;
}
@Override
public String getType() {
return "NTLM";
}
@Override
public boolean matches(String type, URI uri, String realm) {
return "NTLM".equalsIgnoreCase(type) && proxyUri.equals(uri);
}
@Override
public AuthenticationResult authenticate(Request request, ContentResponse response,
HeaderInfo headerInfo, Context context) {
// Implement NTLM authentication logic
// This typically involves multiple challenge/response exchanges
String ntlmMessage = createNTLMResponse(headerInfo.getParameters());
return AuthenticationResult.from(context.getURI(), context.getRealm(), "Proxy-Authorization", ntlmMessage);
}
private String createNTLMResponse(Map<String, String> challenge) {
// Implement NTLM message creation
// This would typically use a library like JCIFS
return "NTLM " + base64EncodedNTLMMessage;
}
}public class DynamicProxySelector {
private final List<ProxyConfiguration.Proxy> proxies;
private final Map<String, ProxyConfiguration.Proxy> domainProxies;
public DynamicProxySelector() {
this.proxies = new ArrayList<>();
this.domainProxies = new HashMap<>();
// Configure domain-specific proxies
domainProxies.put("api.partner1.com", new HttpProxy("partner1-proxy.com", 8080));
domainProxies.put("api.partner2.com", new Socks5Proxy("partner2-socks.com", 1080));
// Default corporate proxy
proxies.add(new HttpProxy("corporate-proxy.company.com", 8080));
}
public ProxyConfiguration.Proxy selectProxy(URI uri) {
String host = uri.getHost();
// Check for domain-specific proxy
ProxyConfiguration.Proxy domainProxy = domainProxies.get(host);
if (domainProxy != null) {
return domainProxy;
}
// Check for wildcard domain matches
for (Map.Entry<String, ProxyConfiguration.Proxy> entry : domainProxies.entrySet()) {
if (host.endsWith(entry.getKey().substring(1))) { // Remove * from *.domain.com
return entry.getValue();
}
}
// Return default proxy
return proxies.get(0);
}
}public class ProxyHealthChecker {
private final HttpClient testClient;
private final Map<ProxyConfiguration.Proxy, Boolean> proxyHealth;
public ProxyHealthChecker() throws Exception {
this.testClient = new HttpClient();
this.testClient.setConnectTimeout(5000);
this.testClient.setIdleTimeout(10000);
this.testClient.start();
this.proxyHealth = new ConcurrentHashMap<>();
}
public boolean isProxyHealthy(ProxyConfiguration.Proxy proxy) {
return proxyHealth.computeIfAbsent(proxy, this::checkProxyHealth);
}
private boolean checkProxyHealth(ProxyConfiguration.Proxy proxy) {
try {
// Create temporary client with this proxy
HttpClient proxyTestClient = new HttpClient();
ProxyConfiguration testProxyConfig = new ProxyConfiguration();
testProxyConfig.addProxy(proxy);
// Set proxy configuration on test client
proxyTestClient.start();
try {
// Test proxy with a simple request
ContentResponse response = proxyTestClient.GET("http://httpbin.org/ip");
return response.getStatus() == 200;
} finally {
proxyTestClient.stop();
}
} catch (Exception e) {
return false;
}
}
public void scheduleHealthChecks(ScheduledExecutorService scheduler) {
scheduler.scheduleAtFixedRate(() -> {
proxyHealth.keySet().forEach(proxy -> {
boolean healthy = checkProxyHealth(proxy);
proxyHealth.put(proxy, healthy);
if (!healthy) {
System.err.println("Proxy unhealthy: " + proxy.getAddress());
}
});
}, 0, 60, TimeUnit.SECONDS);
}
}Configure proxy bypass for specific destinations.
// Configure proxy but exclude certain hosts
Set<String> noProxyHosts = Set.of(
"localhost",
"127.0.0.1",
"*.local",
"*.company.com",
"internal-api.example.com"
);
HttpProxy proxy = new HttpProxy(
new Origin.Address("proxy.company.com", 8080),
false,
Collections.singleton("*"), // Include all hosts by default
noProxyHosts // Exclude these hosts from proxy
);
client.getProxyConfiguration().addProxy(proxy);
// Requests to excluded hosts will bypass proxy
ContentResponse directResponse = client.GET("https://internal-api.company.com/data");
ContentResponse proxiedResponse = client.GET("https://external-api.example.com/data");public class EnvironmentProxyConfig {
public static void configureFromEnvironment(HttpClient client) {
// Read proxy configuration from environment variables
String httpProxy = System.getenv("HTTP_PROXY");
String httpsProxy = System.getenv("HTTPS_PROXY");
String noProxy = System.getenv("NO_PROXY");
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
if (httpProxy != null) {
URI proxyUri = URI.create(httpProxy);
HttpProxy proxy = new HttpProxy(proxyUri.getHost(), proxyUri.getPort());
// Configure no-proxy hosts if specified
if (noProxy != null) {
Set<String> noProxyHosts = Set.of(noProxy.split(","));
proxy = new HttpProxy(
new Origin.Address(proxyUri.getHost(), proxyUri.getPort()),
false,
Collections.singleton("*"),
noProxyHosts
);
}
proxyConfig.addProxy(proxy);
// Configure proxy authentication if present in URI
String userInfo = proxyUri.getUserInfo();
if (userInfo != null) {
String[] credentials = userInfo.split(":");
if (credentials.length == 2) {
BasicAuthentication proxyAuth = new BasicAuthentication(
proxyUri,
null,
credentials[0],
credentials[1]
);
client.getAuthenticationStore().addAuthentication(proxyAuth);
}
}
}
}
}
// Usage
EnvironmentProxyConfig.configureFromEnvironment(client);public class ProxyDebugger {
public static void debugProxyConnection(HttpClient client, String testUrl) {
ProxyConfiguration proxyConfig = client.getProxyConfiguration();
System.out.println("Configured proxies:");
for (ProxyConfiguration.Proxy proxy : proxyConfig.getProxies()) {
System.out.println(" " + proxy.getClass().getSimpleName() +
" - " + proxy.getAddress() +
" (secure: " + proxy.isSecure() + ")");
System.out.println(" Included: " + proxy.getIncludedAddresses());
System.out.println(" Excluded: " + proxy.getExcludedAddresses());
}
// Test proxy selection for target URL
try {
URI uri = URI.create(testUrl);
Origin origin = new Origin("https", uri.getHost(), uri.getPort());
ProxyConfiguration.Proxy selectedProxy = proxyConfig.match(origin);
if (selectedProxy != null) {
System.out.println("Selected proxy for " + testUrl + ": " + selectedProxy.getAddress());
} else {
System.out.println("No proxy selected for " + testUrl + " (direct connection)");
}
} catch (Exception e) {
System.err.println("Error testing proxy selection: " + e.getMessage());
}
}
}client.newRequest("https://api.example.com/data")
.send(result -> {
if (result.isFailed()) {
Throwable failure = result.getFailure();
if (failure instanceof ConnectException) {
System.err.println("Failed to connect to proxy server");
} else if (failure instanceof HttpRequestException) {
HttpRequestException httpEx = (HttpRequestException) failure;
System.err.println("Proxy request failed: " + httpEx.getMessage());
} else if (failure.getMessage().contains("407")) {
System.err.println("Proxy authentication required");
} else {
System.err.println("Proxy-related error: " + failure.getMessage());
}
}
});Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-client