Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Apache HttpClient
https://github.com/apache/httpcomponents-client
Admin
Apache HttpComponents Client is a powerful and flexible Java-based HTTP client that supports all
...
Tokens:
28,485
Snippets:
803
Trust Score:
9.1
Update:
1 week ago
Context
Skills
Chat
Benchmark
82.9
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Apache HttpComponents Client Apache HttpClient is a robust, feature-rich HTTP client library for Java applications. It provides comprehensive support for HTTP/1.1 and HTTP/2 protocols, offering both synchronous (classic blocking I/O) and asynchronous (NIO-based) client implementations. The library is designed for high-performance, thread-safe HTTP communication with features including connection pooling, authentication, cookies, SSL/TLS, caching, and transparent content compression. The library is modular with several components: `httpclient5` (core classic and async clients), `httpclient5-fluent` (simplified API), `httpclient5-cache` (HTTP caching), `httpclient5-sse` (Server-Sent Events), and `httpclient5-websocket` (WebSocket support). HttpClient conforms to modern HTTP specifications (RFC 9110-9113) and supports advanced features like HTTP/2 multiplexing, digest/basic/bearer authentication, cookie management per RFC 6265, and connection management with pooling. --- ## Basic HTTP GET Request with Response Handler Execute a simple GET request using the recommended pattern with a response handler that automatically manages connection release and converts the response to a custom result object. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.message.StatusLine; public class BasicGetExample { public static void main(String[] args) throws Exception { try (CloseableHttpClient httpclient = HttpClients.createDefault()) { HttpGet httpget = new HttpGet("http://httpbin.org/get"); // Execute with response handler - automatically releases connection String result = httpclient.execute(httpget, response -> { System.out.println("Status: " + new StatusLine(response)); return EntityUtils.toString(response.getEntity()); }); System.out.println("Response body: " + result); } } } // Output: // Status: HTTP/1.1 200 OK // Response body: { "args": {}, "headers": {...}, "origin": "...", "url": "..." } ``` --- ## HTTP POST with Form Data Submit form data using URL-encoded POST request with the ClassicRequestBuilder for flexible request construction. ```java import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import java.net.URI; public class FormPostExample { public static void main(String[] args) throws Exception { try (CloseableHttpClient httpclient = HttpClients.createDefault()) { ClassicHttpRequest request = ClassicRequestBuilder.post() .setUri(new URI("https://httpbin.org/post")) .addParameter("username", "testuser") .addParameter("password", "secret123") .addParameter("remember", "true") .build(); httpclient.execute(request, response -> { System.out.println("Status: " + response.getCode()); System.out.println("Response: " + EntityUtils.toString(response.getEntity())); return null; }); } } } ``` --- ## Fluent API for Simple Requests The fluent API provides a simplified, chainable interface for common HTTP operations without manual connection management. ```java import org.apache.hc.client5.http.fluent.Form; import org.apache.hc.client5.http.fluent.Request; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.util.Timeout; import java.io.File; public class FluentApiExample { public static void main(String[] args) throws Exception { // Simple GET with timeout settings String content = Request.get("http://httpbin.org/get") .connectTimeout(Timeout.ofSeconds(5)) .responseTimeout(Timeout.ofSeconds(10)) .execute() .returnContent() .asString(); System.out.println("GET Response: " + content); // POST with JSON body byte[] response = Request.post("http://httpbin.org/post") .useExpectContinue() .version(HttpVersion.HTTP_1_1) .bodyString("{\"name\":\"test\",\"value\":123}", ContentType.APPLICATION_JSON) .execute() .returnContent() .asBytes(); // POST with form data through proxy Request.post("http://httpbin.org/post") .addHeader("X-Custom-Header", "custom-value") .viaProxy(new HttpHost("myproxy", 8080)) .bodyForm(Form.form() .add("username", "admin") .add("password", "secret") .build()) .execute() .saveContent(new File("response.txt")); } } ``` --- ## Multipart Form File Upload Upload files using multipart/form-data encoding with mixed content types including binary files and text fields. ```java import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.entity.mime.FileBody; import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; import org.apache.hc.client5.http.entity.mime.StringBody; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.EntityUtils; import java.io.File; public class MultipartUploadExample { public static void main(String[] args) throws Exception { try (CloseableHttpClient httpclient = HttpClients.createDefault()) { HttpPost httppost = new HttpPost("http://httpbin.org/post"); FileBody fileBody = new FileBody(new File("/path/to/document.pdf")); StringBody comment = new StringBody("File upload test", ContentType.TEXT_PLAIN); StringBody filename = new StringBody("document.pdf", ContentType.TEXT_PLAIN); HttpEntity reqEntity = MultipartEntityBuilder.create() .addPart("file", fileBody) .addPart("comment", comment) .addPart("filename", filename) .addBinaryBody("image", new File("/path/to/image.png"), ContentType.IMAGE_PNG, "image.png") .addTextBody("description", "Test upload with multiple files") .build(); httppost.setEntity(reqEntity); httpclient.execute(httppost, response -> { System.out.println("Upload status: " + response.getCode()); System.out.println("Response: " + EntityUtils.toString(response.getEntity())); return null; }); } } } ``` --- ## Basic and Digest Authentication Configure HTTP authentication with credentials provider for automatic handling of Basic and Digest authentication challenges. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.message.StatusLine; public class AuthenticationExample { public static void main(String[] args) throws Exception { HttpHost targetHost = new HttpHost("https", "httpbin.org", 443); try (CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCredentialsProvider(CredentialsProviderBuilder.create() .add(targetHost, "username", "password".toCharArray()) .build()) .build()) { HttpGet httpget = new HttpGet("https://httpbin.org/basic-auth/username/password"); httpclient.execute(httpget, response -> { System.out.println("Auth result: " + new StatusLine(response)); System.out.println("Body: " + EntityUtils.toString(response.getEntity())); return null; }); } } } // Output: // Auth result: HTTP/1.1 200 OK // Body: { "authenticated": true, "user": "username" } ``` --- ## Custom SSL/TLS Configuration Configure custom SSL context with specific TLS versions, custom trust strategy, and hostname verification. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.TlsConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; import org.apache.hc.client5.http.ssl.TlsSocketStrategy; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.ssl.TLS; import org.apache.hc.core5.ssl.SSLContexts; import org.apache.hc.core5.util.Timeout; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import java.security.cert.X509Certificate; public class CustomSslExample { public static void main(String[] args) throws Exception { // Create custom SSL context with trust strategy SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial((chain, authType) -> { // Custom certificate validation logic X509Certificate cert = chain[0]; return "CN=httpbin.org".equalsIgnoreCase( cert.getSubjectX500Principal().getName()); }) .build(); TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy(sslContext); // Configure connection manager with TLS 1.3 only HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() .setTlsSocketStrategy(tlsStrategy) .setDefaultTlsConfig(TlsConfig.custom() .setHandshakeTimeout(Timeout.ofSeconds(30)) .setSupportedProtocols(TLS.V_1_3) .build()) .build(); try (CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManager(cm) .build()) { HttpGet httpget = new HttpGet("https://httpbin.org/get"); HttpClientContext context = HttpClientContext.create(); httpclient.execute(httpget, context, response -> { EntityUtils.consume(response.getEntity()); SSLSession sslSession = context.getSSLSession(); if (sslSession != null) { System.out.println("Protocol: " + sslSession.getProtocol()); System.out.println("Cipher: " + sslSession.getCipherSuite()); } return null; }); } } } ``` --- ## Connection Pool Configuration Configure connection pooling with custom limits, timeouts, and per-route settings for optimal performance in multi-threaded applications. ```java import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; public class ConnectionPoolExample { public static void main(String[] args) throws Exception { PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(); // Configure pool limits connManager.setMaxTotal(200); // Max total connections connManager.setDefaultMaxPerRoute(20); // Max connections per route // Set higher limit for specific host HttpHost targetHost = new HttpHost("https", "api.example.com", 443); connManager.setMaxPerRoute(new HttpRoute(targetHost), 50); // Configure socket settings connManager.setDefaultSocketConfig(SocketConfig.custom() .setSoTimeout(Timeout.ofSeconds(30)) .setTcpNoDelay(true) .setSoKeepAlive(true) .build()); // Configure connection settings connManager.setDefaultConnectionConfig(ConnectionConfig.custom() .setConnectTimeout(Timeout.ofSeconds(10)) .setSocketTimeout(Timeout.ofSeconds(30)) .setValidateAfterInactivity(TimeValue.ofSeconds(10)) .setTimeToLive(TimeValue.ofMinutes(5)) .build()); try (CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManager(connManager) .evictExpiredConnections() .evictIdleConnections(TimeValue.ofMinutes(1)) .build()) { // Safe to use from multiple threads HttpGet httpget = new HttpGet("https://httpbin.org/get"); httpclient.execute(httpget, response -> { System.out.println("Status: " + response.getCode()); EntityUtils.consume(response.getEntity()); return null; }); } } } ``` --- ## Async HTTP Client with Callbacks Execute non-blocking HTTP requests using the async client with Future-based and callback-based result handling. ```java import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; import org.apache.hc.client5.http.async.methods.SimpleRequestProducer; import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.core5.concurrent.FutureCallback; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.message.StatusLine; import org.apache.hc.core5.io.CloseMode; import org.apache.hc.core5.reactor.IOReactorConfig; import org.apache.hc.core5.util.Timeout; import java.util.concurrent.Future; public class AsyncClientExample { public static void main(String[] args) throws Exception { IOReactorConfig ioConfig = IOReactorConfig.custom() .setSoTimeout(Timeout.ofSeconds(5)) .setIoThreadCount(Runtime.getRuntime().availableProcessors()) .build(); CloseableHttpAsyncClient client = HttpAsyncClients.custom() .setIOReactorConfig(ioConfig) .build(); client.start(); HttpHost target = new HttpHost("https", "httpbin.org"); String[] paths = {"/get", "/ip", "/user-agent", "/headers"}; for (String path : paths) { SimpleHttpRequest request = SimpleRequestBuilder.get() .setHttpHost(target) .setPath(path) .build(); Future<SimpleHttpResponse> future = client.execute( SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() { @Override public void completed(SimpleHttpResponse response) { System.out.println(path + " -> " + new StatusLine(response)); System.out.println("Body: " + response.getBodyText()); } @Override public void failed(Exception ex) { System.err.println(path + " failed: " + ex.getMessage()); } @Override public void cancelled() { System.out.println(path + " cancelled"); } }); // Optionally wait for completion future.get(); } client.close(CloseMode.GRACEFUL); } } ``` --- ## HTTP Proxy Configuration Route requests through HTTP or SOCKS proxies with optional proxy authentication. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.entity.EntityUtils; public class ProxyExample { public static void main(String[] args) throws Exception { HttpHost target = new HttpHost("https", "httpbin.org", 443); HttpHost proxy = new HttpHost("http", "proxy.example.com", 8080); // With proxy authentication try (CloseableHttpClient httpclient = HttpClients.custom() .setProxy(proxy) .setDefaultCredentialsProvider(CredentialsProviderBuilder.create() .add(proxy, "proxyuser", "proxypass".toCharArray()) .build()) .build()) { HttpGet request = new HttpGet("/get"); request.setConfig(RequestConfig.custom() .setProxy(proxy) .build()); System.out.println("Executing via proxy: " + proxy); httpclient.execute(target, request, response -> { System.out.println("Status: " + response.getCode()); System.out.println("Response: " + EntityUtils.toString(response.getEntity())); return null; }); } } } ``` --- ## Cookie Management Handle HTTP cookies with custom cookie store for session management and stateful interactions. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.cookie.BasicCookieStore; import org.apache.hc.client5.http.cookie.Cookie; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import java.net.URI; import java.util.List; public class CookieManagementExample { public static void main(String[] args) throws Exception { BasicCookieStore cookieStore = new BasicCookieStore(); try (CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCookieStore(cookieStore) .build()) { // First request - server may set cookies HttpGet httpget = new HttpGet("https://httpbin.org/cookies/set/session/abc123"); httpclient.execute(httpget, response -> { EntityUtils.consume(response.getEntity()); return null; }); // Display stored cookies System.out.println("Stored cookies:"); List<Cookie> cookies = cookieStore.getCookies(); for (Cookie cookie : cookies) { System.out.println(" " + cookie.getName() + "=" + cookie.getValue() + " (domain: " + cookie.getDomain() + ")"); } // Second request - cookies sent automatically var request = ClassicRequestBuilder.get() .setUri(new URI("https://httpbin.org/cookies")) .build(); httpclient.execute(request, response -> { System.out.println("Cookies echo: " + EntityUtils.toString(response.getEntity())); return null; }); } } } ``` --- ## Request and Response Interceptors Add custom interceptors for logging, header manipulation, or request/response modification. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.ChainElement; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.EntityDetails; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponseInterceptor; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.protocol.HttpContext; import java.util.concurrent.atomic.AtomicLong; public class InterceptorExample { public static void main(String[] args) throws Exception { AtomicLong requestCounter = new AtomicLong(0); try (CloseableHttpClient httpclient = HttpClients.custom() // Request interceptor - add custom headers .addRequestInterceptorFirst((HttpRequestInterceptor) (request, entity, context) -> { long requestId = requestCounter.incrementAndGet(); request.setHeader("X-Request-ID", String.valueOf(requestId)); request.setHeader("X-Client-Version", "1.0.0"); System.out.println(">>> Request #" + requestId + ": " + request.getMethod() + " " + request.getUri()); }) // Response interceptor - log response .addResponseInterceptorLast((HttpResponseInterceptor) (response, entity, context) -> { System.out.println("<<< Response: " + response.getCode() + " " + response.getReasonPhrase()); }) // Execution interceptor - can short-circuit request .addExecInterceptorAfter(ChainElement.PROTOCOL.name(), "rate-limiter", (request, scope, chain) -> { // Could implement rate limiting, caching, etc. System.out.println("--- Processing request through custom interceptor"); return chain.proceed(request, scope); }) .build()) { for (int i = 0; i < 3; i++) { HttpGet httpget = new HttpGet("http://httpbin.org/get"); httpclient.execute(httpget, response -> { EntityUtils.consume(response.getEntity()); return null; }); } } } } ``` --- ## HTTP Caching Client Use the caching HTTP client to cache responses and reduce network traffic with RFC 9111 compliant caching. ```java import org.apache.hc.client5.http.cache.CacheContextBuilder; import org.apache.hc.client5.http.cache.HttpCacheContext; import org.apache.hc.client5.http.cache.HttpCacheEntry; import org.apache.hc.client5.http.cache.RequestCacheControl; import org.apache.hc.client5.http.impl.cache.CacheConfig; import org.apache.hc.client5.http.impl.cache.CachingHttpClients; import org.apache.hc.client5.http.impl.cache.HeapResourceFactory; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; public class CachingClientExample { public static void main(String[] args) throws Exception { HttpHost target = new HttpHost("https", "www.apache.org"); try (CloseableHttpClient httpclient = CachingHttpClients.custom() .setCacheConfig(CacheConfig.custom() .setMaxCacheEntries(1000) .setMaxObjectSize(500000) // 500KB max cached object .setHeuristicCachingEnabled(true) .setSharedCache(false) .build()) .setResourceFactory(HeapResourceFactory.INSTANCE) .build()) { // First request - will fetch from origin HttpCacheContext context = CacheContextBuilder.create() .setCacheControl(RequestCacheControl.DEFAULT) .build(); var request1 = ClassicRequestBuilder.get() .setHttpHost(target) .setPath("/") .build(); httpclient.execute(request1, context, response -> { EntityUtils.consume(response.getEntity()); System.out.println("First request - Cache status: " + context.getCacheResponseStatus()); return null; }); // Second request - may be served from cache var request2 = ClassicRequestBuilder.get() .setHttpHost(target) .setPath("/") .build(); httpclient.execute(request2, context, response -> { EntityUtils.consume(response.getEntity()); System.out.println("Second request - Cache status: " + context.getCacheResponseStatus()); HttpCacheEntry entry = context.getCacheEntry(); if (entry != null) { System.out.println("Cached at: " + entry.getInstant()); System.out.println("Expires: " + entry.getExpires()); } return null; }); // Force revalidation context.setRequestCacheControl(RequestCacheControl.builder() .setMaxAge(0) .build()); httpclient.execute(request2, context, response -> { EntityUtils.consume(response.getEntity()); System.out.println("Forced revalidation - Cache status: " + context.getCacheResponseStatus()); return null; }); } } } // Output: // First request - Cache status: CACHE_MISS // Second request - Cache status: CACHE_HIT // Forced revalidation - Cache status: VALIDATED ``` --- ## Multi-threaded Request Execution Execute concurrent requests safely using connection pooling with proper thread management. ```java import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.core5.http.io.entity.EntityUtils; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class MultiThreadedExample { public static void main(String[] args) throws Exception { PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(100); cm.setDefaultMaxPerRoute(20); try (CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManager(cm) .build()) { String[] urls = { "http://httpbin.org/get", "http://httpbin.org/ip", "http://httpbin.org/user-agent", "http://httpbin.org/headers", "http://httpbin.org/uuid" }; ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i < urls.length; i++) { final int threadId = i + 1; final String url = urls[i]; executor.submit(() -> { try { HttpGet httpget = new HttpGet(url); HttpClientContext context = HttpClientContext.create(); httpclient.execute(httpget, context, response -> { byte[] content = EntityUtils.toByteArray(response.getEntity()); System.out.println("Thread " + threadId + ": " + url + " -> " + content.length + " bytes"); return null; }); } catch (Exception e) { System.err.println("Thread " + threadId + " error: " + e.getMessage()); } }); } executor.shutdown(); executor.awaitTermination(30, TimeUnit.SECONDS); } } } ``` --- ## WebSocket Client Establish WebSocket connections with compression support for real-time bidirectional communication. ```java import org.apache.hc.client5.http.websocket.api.WebSocket; import org.apache.hc.client5.http.websocket.api.WebSocketClientConfig; import org.apache.hc.client5.http.websocket.api.WebSocketListener; import org.apache.hc.client5.http.websocket.client.CloseableWebSocketClient; import org.apache.hc.client5.http.websocket.client.WebSocketClientBuilder; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; import java.net.URI; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; public class WebSocketClientExample { public static void main(String[] args) throws Exception { URI uri = URI.create("ws://localhost:8080/echo"); CountDownLatch done = new CountDownLatch(1); WebSocketClientConfig config = WebSocketClientConfig.custom() .enablePerMessageDeflate(true) .offerServerNoContextTakeover(true) .offerClientNoContextTakeover(true) .setCloseWaitTimeout(Timeout.ofSeconds(5)) .build(); try (CloseableWebSocketClient client = WebSocketClientBuilder.create() .defaultConfig(config) .build()) { client.start(); client.connect(uri, new WebSocketListener() { private WebSocket ws; @Override public void onOpen(WebSocket webSocket) { this.ws = webSocket; System.out.println("Connected to: " + uri); ws.sendText("Hello WebSocket!", true); } @Override public void onText(CharBuffer text, boolean last) { System.out.println("Received: " + text); if (last) { ws.close(1000, "Done"); } } @Override public void onBinary(ByteBuffer data, boolean last) { System.out.println("Binary data: " + data.remaining() + " bytes"); } @Override public void onPong(ByteBuffer payload) { System.out.println("Pong received"); } @Override public void onClose(int code, String reason) { System.out.println("Closed: " + code + " - " + reason); done.countDown(); } @Override public void onError(Throwable ex) { ex.printStackTrace(); done.countDown(); } }, config); done.await(30, TimeUnit.SECONDS); client.initiateShutdown(); client.awaitShutdown(TimeValue.ofSeconds(5)); } } } ``` --- ## Server-Sent Events (SSE) Client Subscribe to Server-Sent Events streams with automatic reconnection and backoff handling. ```java import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.client5.http.sse.EventSource; import org.apache.hc.client5.http.sse.EventSourceConfig; import org.apache.hc.client5.http.sse.EventSourceListener; import org.apache.hc.client5.http.sse.SseExecutor; import org.apache.hc.client5.http.sse.impl.ExponentialJitterBackoff; import org.apache.hc.client5.http.sse.impl.SseParser; import org.apache.hc.core5.reactor.IOReactorConfig; import org.apache.hc.core5.util.TimeValue; import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledThreadPoolExecutor; public class SseClientExample { public static void main(String[] args) throws Exception { URI sseUri = URI.create("https://stream.example.com/events"); CountDownLatch done = new CountDownLatch(1); IOReactorConfig ioConfig = IOReactorConfig.custom() .setSoKeepAlive(true) .setTcpNoDelay(true) .build(); CloseableHttpAsyncClient httpClient = HttpAsyncClientBuilder.create() .setIOReactorConfig(ioConfig) .evictExpiredConnections() .evictIdleConnections(TimeValue.ofMinutes(1)) .build(); ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(2); scheduler.setRemoveOnCancelPolicy(true); EventSourceConfig config = EventSourceConfig.builder() .backoff(new ExponentialJitterBackoff(500L, 30000L, 2.0, 250L)) .maxReconnects(-1) // Unlimited reconnects .build(); Map<String, String> headers = new HashMap<>(); headers.put("Authorization", "Bearer token123"); SseExecutor executor = SseExecutor.custom() .setHttpClient(httpClient) .setScheduler(scheduler) .setEventSourceConfig(config) .setDefaultHeaders(headers) .setParserStrategy(SseParser.BYTE) .build(); EventSource eventSource = executor.open(sseUri, headers, new EventSourceListener() { @Override public void onOpen() { System.out.println("SSE connection opened"); } @Override public void onEvent(String id, String type, String data) { System.out.println("Event [" + type + "] id=" + id + ": " + data); } @Override public void onClosed() { System.out.println("SSE connection closed"); done.countDown(); } @Override public void onFailure(Throwable t, boolean willReconnect) { System.err.println("SSE error: " + t.getMessage() + " (reconnect=" + willReconnect + ")"); if (!willReconnect) { done.countDown(); } } }, config, SseParser.BYTE, scheduler, Runnable::run); eventSource.start(); // Add shutdown hook Runtime.getRuntime().addShutdownHook(new Thread(() -> { eventSource.cancel(); executor.close(); scheduler.shutdownNow(); })); done.await(); } } ``` --- ## Complete Request Configuration Comprehensive client configuration demonstrating all major customization options including connection management, authentication, cookies, and request settings. ```java import org.apache.hc.client5.http.ContextBuilder; import org.apache.hc.client5.http.HttpRoute; import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.config.TlsConfig; import org.apache.hc.client5.http.cookie.BasicCookieStore; import org.apache.hc.client5.http.cookie.StandardCookieSpec; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.client5.http.io.HttpClientConnectionManager; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.ssl.TLS; import org.apache.hc.core5.ssl.SSLContexts; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; import java.util.Arrays; public class FullConfigurationExample { public static void main(String[] args) throws Exception { // Connection manager with full configuration HttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create() .setTlsSocketStrategy(new DefaultClientTlsStrategy(SSLContexts.createDefault())) .setDefaultSocketConfig(SocketConfig.custom() .setSoTimeout(Timeout.ofSeconds(30)) .setTcpNoDelay(true) .setSoKeepAlive(true) .build()) .setDefaultConnectionConfig(ConnectionConfig.custom() .setConnectTimeout(Timeout.ofSeconds(10)) .setSocketTimeout(Timeout.ofSeconds(30)) .setValidateAfterInactivity(TimeValue.ofSeconds(5)) .setTimeToLive(TimeValue.ofMinutes(10)) .build()) .setDefaultTlsConfig(TlsConfig.custom() .setHandshakeTimeout(Timeout.ofSeconds(15)) .setSupportedProtocols(TLS.V_1_2, TLS.V_1_3) .build()) .setMaxConnTotal(200) .setMaxConnPerRoute(25) .build(); // Default request configuration RequestConfig defaultRequestConfig = RequestConfig.custom() .setCookieSpec(StandardCookieSpec.STRICT) .setExpectContinueEnabled(true) .setRedirectsEnabled(true) .setMaxRedirects(5) .setCircularRedirectsAllowed(false) .setTargetPreferredAuthSchemes(Arrays.asList( StandardAuthScheme.DIGEST, StandardAuthScheme.BASIC)) .setConnectionRequestTimeout(Timeout.ofSeconds(5)) .setResponseTimeout(Timeout.ofSeconds(30)) .build(); BasicCookieStore cookieStore = new BasicCookieStore(); try (CloseableHttpClient httpclient = HttpClients.custom() .setConnectionManager(connManager) .setDefaultCookieStore(cookieStore) .setDefaultCredentialsProvider(CredentialsProviderBuilder.create() .add(new HttpHost("api.example.com", 443), "user", "pass".toCharArray()) .build()) .setDefaultRequestConfig(defaultRequestConfig) .setUserAgent("MyApp/1.0 HttpClient/5.x") .evictExpiredConnections() .evictIdleConnections(TimeValue.ofMinutes(2)) .build()) { HttpGet httpget = new HttpGet("https://httpbin.org/get"); // Override config per-request httpget.setConfig(RequestConfig.copy(defaultRequestConfig) .setResponseTimeout(Timeout.ofSeconds(60)) .build()); // Custom context for this request HttpClientContext context = ContextBuilder.create() .useCookieStore(cookieStore) .build(); httpclient.execute(httpget, context, response -> { System.out.println("Status: " + response.getCode()); System.out.println("Route: " + context.getHttpRoute()); System.out.println("Response: " + EntityUtils.toString(response.getEntity())); return null; }); } } } ``` --- Apache HttpClient is ideal for building robust HTTP client applications including REST API consumers, web service clients, microservice communication, web crawlers, and automated testing frameworks. Its comprehensive feature set supports enterprise requirements like connection pooling for scalability, authentication for secure access, caching for performance optimization, and async operations for high-throughput scenarios. The library integrates seamlessly with Java applications through Maven/Gradle dependencies, supports both blocking and non-blocking I/O patterns, and provides extensive customization through builders and interceptors. Common integration patterns include using the fluent API for simple scripts, the classic API for traditional request-response workflows, and the async API for reactive or high-concurrency applications requiring HTTP/2 multiplexing or WebSocket/SSE real-time communication.