Helidon WebClient is a comprehensive HTTP client library for Java microservices supporting HTTP/1.1, HTTP/2, and protocol negotiation with virtual thread support.
—
Advanced connection handling including custom connections, connection caching, proxy support, TLS configuration, and DNS resolution strategies.
Abstraction for client network connections enabling custom connections for testing and advanced use cases.
/**
* Get data reader for reading responses
* @return data reader instance
*/
DataReader reader();
/**
* Get data writer for writing requests
* @return data writer instance
*/
DataWriter writer();
/**
* Get connection identifier
* @return unique connection identifier
*/
String channelId();
/**
* Get underlying socket
* @return Helidon socket instance
*/
HelidonSocket helidonSocket();
/**
* Configure read timeout for this connection
* @param readTimeout timeout duration
*/
void readTimeout(Duration readTimeout);
/**
* Check if connection supports Expect: 100-Continue
* @return true if 100-Continue is supported
*/
default boolean allowExpectContinue();
/**
* Configure Expect: 100-Continue support
* @param allowExpectContinue true to enable support
*/
default void allowExpectContinue(boolean allowExpectContinue);
/**
* Release/close the connection
*/
default void closeResource();Usage Examples:
import io.helidon.webclient.api.ClientConnection;
import io.helidon.webclient.api.TcpClientConnection;
// Use explicit connection for request
ClientConnection connection = TcpClientConnection.create(
socketAddress, tls, socketOptions, dnsResolver, proxy);
String response = client.get("/api/data")
.connection(connection)
.requestEntity(String.class);
// Connection will be reused for subsequent requests using the same connectionConcrete implementation of ClientConnection for TCP-based protocols.
/**
* Create TCP client connection
* @param socketAddress target socket address
* @param tls TLS configuration
* @param socketOptions socket options
* @param dnsResolver DNS resolver
* @param proxy proxy configuration
* @return new TCP connection
*/
static TcpClientConnection create(
InetSocketAddress socketAddress,
Tls tls,
SocketOptions socketOptions,
DnsResolver dnsResolver,
Optional<Proxy> proxy);
/**
* Create TCP client connection with additional parameters
* @param webClient associated web client
* @param socketAddress target socket address
* @param socketOptions socket options
* @param tls TLS configuration
* @param dnsResolver DNS resolver
* @param proxy proxy configuration
* @return new TCP connection
*/
static TcpClientConnection create(
WebClient webClient,
InetSocketAddress socketAddress,
SocketOptions socketOptions,
Tls tls,
DnsResolver dnsResolver,
Optional<Proxy> proxy);Intelligent connection pooling and caching with configurable strategies to improve performance.
/**
* Interface for connection caching implementations
*/
public interface ClientConnectionCache {
/**
* Get cached connection for key
* @param key connection key
* @return cached connection if available
*/
Optional<ClientConnection> connection(ConnectionKey key);
/**
* Create and cache new connection
* @param key connection key
* @param connectionSupplier supplier to create connection
* @return new cached connection
*/
ClientConnection newConnection(ConnectionKey key, Supplier<ClientConnection> connectionSupplier);
}
/**
* Key for connection caching based on target and configuration
*/
public record ConnectionKey(
String host,
int port,
boolean tls,
DnsAddressLookup dnsAddressLookup,
Optional<Proxy> proxy
) {
// Connection caching key
}Configuration Examples:
// Configure connection caching
WebClient client = WebClient.builder()
.connectionCacheSize(50) // Maximum cached connections
.shareConnectionCache(true) // Share cache across client instances
.build();Pluggable DNS resolution with multiple strategies for handling hostname resolution.
/**
* Strategy for DNS address lookup
*/
public interface DnsAddressLookup {
/**
* Resolve hostname to IP addresses
* @param hostname hostname to resolve
* @return list of resolved IP addresses
*/
List<InetAddress> listAddresses(String hostname);
/**
* Default Java DNS lookup
* @return default lookup implementation
*/
static DnsAddressLookup defaultLookup();
/**
* Return only first resolved address
* @return first-address lookup implementation
*/
static DnsAddressLookup firstAddress();
/**
* Round-robin through resolved addresses
* @return round-robin lookup implementation
*/
static DnsAddressLookup roundRobin();
}
/**
* DNS resolution strategy interface
*/
public interface DnsResolver {
/**
* Get address lookup implementation
* @return address lookup instance
*/
DnsAddressLookup addressLookup();
}Usage Examples:
import io.helidon.webclient.api.DnsAddressLookup;
// Configure DNS resolution strategy
WebClient client = WebClient.builder()
.dnsAddressLookup(DnsAddressLookup.roundRobin()) // Round-robin through IPs
.build();
// Or use first available address only
WebClient client = WebClient.builder()
.dnsAddressLookup(DnsAddressLookup.firstAddress())
.build();
// Custom DNS resolution
WebClient client = WebClient.builder()
.dnsResolver(customDnsResolver)
.build();Comprehensive proxy support including HTTP proxies, system proxies, and no-proxy patterns.
/**
* Create proxy configuration builder
* @return new proxy builder
*/
static Proxy.Builder builder();
/**
* No-proxy instance (disables proxy usage)
* @return no-proxy configuration
*/
static Proxy noProxy();
/**
* Create proxy from system properties
* @return proxy configuration from system settings
*/
static Proxy create();
/**
* Create proxy from configuration
* @param config configuration instance
* @return proxy configuration
*/
static Proxy create(Config config);
/**
* Create proxied socket
* @param webClient associated web client
* @param inetSocketAddress target address
* @param socketOptions socket options
* @param tls whether connection uses TLS
* @return proxied socket
*/
Socket tcpSocket(WebClient webClient, InetSocketAddress inetSocketAddress,
SocketOptions socketOptions, boolean tls);
/**
* Get proxy type
* @return proxy type
*/
ProxyType type();
/**
* Check if URI bypasses proxy (matches no-proxy patterns)
* @param uri target URI
* @return true if URI should bypass proxy
*/
boolean isNoHosts(InetSocketAddress uri);
/**
* Check if using system proxy settings
* @param uri target URI
* @return true if using system proxy
*/
boolean isUsingSystemProxy(String uri);
/**
* Get proxy host
* @return proxy host
*/
String host();
/**
* Get proxy port
* @return proxy port
*/
int port();
/**
* Get proxy username
* @return username for proxy authentication
*/
Optional<String> username();
/**
* Get proxy password
* @return password for proxy authentication
*/
Optional<char[]> password();Proxy Builder:
public static class Builder {
/**
* Set proxy type
* @param type proxy type
* @return builder instance
*/
Builder type(ProxyType type);
/**
* Set proxy host
* @param host proxy host
* @return builder instance
*/
Builder host(String host);
/**
* Set proxy port
* @param port proxy port
* @return builder instance
*/
Builder port(int port);
/**
* Set proxy username
* @param username username for authentication
* @return builder instance
*/
Builder username(String username);
/**
* Set proxy password
* @param password password for authentication
* @return builder instance
*/
Builder password(char[] password);
/**
* Add no-proxy host pattern
* @param noHost host pattern to bypass proxy
* @return builder instance
*/
Builder addNoHost(String noHost);
/**
* Build proxy configuration
* @return proxy instance
*/
Proxy build();
}
/**
* Proxy types
*/
public enum ProxyType {
NONE, // No proxy
SYSTEM, // Use system proxy settings
HTTP // HTTP proxy
}Usage Examples:
import io.helidon.webclient.api.Proxy;
import io.helidon.webclient.api.Proxy.ProxyType;
// HTTP proxy with authentication
WebClient client = WebClient.builder()
.proxy(Proxy.builder()
.type(ProxyType.HTTP)
.host("proxy.example.com")
.port(8080)
.username("user")
.password("pass".toCharArray())
.addNoHost("localhost")
.addNoHost("*.internal.com")
.build())
.build();
// System proxy (uses http.proxyHost, https.proxyHost system properties)
WebClient client = WebClient.builder()
.proxy(Proxy.create())
.build();
// Disable proxy
WebClient client = WebClient.builder()
.proxy(Proxy.noProxy())
.build();
// Per-request proxy override
String response = client.get("/api/data")
.proxy(Proxy.builder()
.type(ProxyType.HTTP)
.host("special-proxy.com")
.port(3128)
.build())
.requestEntity(String.class);Transport Layer Security configuration for secure connections.
/**
* Configure TLS for client connections
* @param tls TLS configuration
* @return client configuration builder
*/
WebClientConfig.Builder tls(Tls tls);Usage Examples:
import io.helidon.common.tls.Tls;
// Configure TLS
WebClient client = WebClient.builder()
.tls(Tls.builder()
.trustAll(false) // Validate certificates
.clientKeyStore(keyStore)
.clientTrustStore(trustStore)
.build())
.build();
// Per-request TLS override
String response = client.get("https://api.example.com/data")
.tls(Tls.builder()
.trustAll(true) // Accept self-signed certificates
.build())
.requestEntity(String.class);Low-level socket configuration for network connections.
/**
* Configure socket options
* @param socketOptions socket configuration
* @return client configuration builder
*/
WebClientConfig.Builder socketOptions(SocketOptions socketOptions);Usage Examples:
import io.helidon.common.socket.SocketOptions;
WebClient client = WebClient.builder()
.socketOptions(SocketOptions.builder()
.connectTimeout(Duration.ofSeconds(10))
.readTimeout(Duration.ofSeconds(30))
.keepAlive(true)
.tcpNoDelay(true)
.receiveBufferSize(65536)
.sendBufferSize(65536)
.build())
.build();Proper resource management for connections and associated resources.
/**
* Base interface for resources that can be released
*/
public interface ReleasableResource {
/**
* Release/close the resource
*/
default void closeResource();
}Usage Examples:
// WebClient implements ReleasableResource
try (WebClient client = WebClient.create()) {
// Use client for requests
String response = client.get("/api/data").requestEntity(String.class);
} // Client connections are automatically closed
// Manual connection management
ClientConnection connection = TcpClientConnection.create(...);
try {
// Use connection
String response = client.get("/api/data")
.connection(connection)
.requestEntity(String.class);
} finally {
connection.closeResource();
}
// HTTP responses should be closed for streaming
try (HttpClientResponse response = client.get("/large-file").request()) {
try (InputStream inputStream = response.inputStream()) {
// Process stream
}
}public interface ClientConnection extends ReleasableResource {
DataReader reader();
DataWriter writer();
String channelId();
HelidonSocket helidonSocket();
void readTimeout(Duration readTimeout);
default boolean allowExpectContinue();
default void allowExpectContinue(boolean allowExpectContinue);
}
public class TcpClientConnection implements ClientConnection {
static TcpClientConnection create(InetSocketAddress socketAddress, Tls tls,
SocketOptions socketOptions, DnsResolver dnsResolver,
Optional<Proxy> proxy);
static TcpClientConnection create(WebClient webClient, InetSocketAddress socketAddress,
SocketOptions socketOptions, Tls tls,
DnsResolver dnsResolver, Optional<Proxy> proxy);
}
public interface ClientConnectionCache {
Optional<ClientConnection> connection(ConnectionKey key);
ClientConnection newConnection(ConnectionKey key, Supplier<ClientConnection> connectionSupplier);
}
public record ConnectionKey(
String host,
int port,
boolean tls,
DnsAddressLookup dnsAddressLookup,
Optional<Proxy> proxy
) {}
public interface DnsAddressLookup {
List<InetAddress> listAddresses(String hostname);
static DnsAddressLookup defaultLookup();
static DnsAddressLookup firstAddress();
static DnsAddressLookup roundRobin();
}
public interface DnsResolver {
DnsAddressLookup addressLookup();
}
public class Proxy {
static Builder builder();
static Proxy noProxy();
static Proxy create();
static Proxy create(Config config);
Socket tcpSocket(WebClient webClient, InetSocketAddress inetSocketAddress,
SocketOptions socketOptions, boolean tls);
ProxyType type();
boolean isNoHosts(InetSocketAddress uri);
boolean isUsingSystemProxy(String uri);
String host();
int port();
Optional<String> username();
Optional<char[]> password();
enum ProxyType { NONE, SYSTEM, HTTP }
static class Builder {
Builder type(ProxyType type);
Builder host(String host);
Builder port(int port);
Builder username(String username);
Builder password(char[] password);
Builder addNoHost(String noHost);
Proxy build();
}
}
public interface ReleasableResource {
default void closeResource();
}Install with Tessl CLI
npx tessl i tessl/maven-io-helidon-webclient--helidon-webclient