Top Related Projects
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
A type-safe HTTP client for Android and the JVM
Mirror of Apache HttpClient
Vert.x is a tool-kit for building reactive applications on the JVM
RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
Spring Framework
Quick Overview
Async Http Client (AHC) is a high-performance, asynchronous HTTP client library for Java. It provides a simple and flexible API for making HTTP requests, supporting both synchronous and asynchronous operations, and is built on top of Netty for efficient network communication.
Pros
- High performance and scalability due to its asynchronous nature
- Supports both synchronous and asynchronous request handling
- Extensive feature set, including WebSocket support, OAuth, and streaming
- Flexible configuration options for fine-tuning performance
Cons
- Steeper learning curve compared to simpler HTTP clients
- Documentation could be more comprehensive and up-to-date
- May be overkill for simple use cases or small projects
- Requires careful management of resources in high-concurrency scenarios
Code Examples
- Making a simple GET request:
AsyncHttpClient client = Dsl.asyncHttpClient();
CompletableFuture<Response> future = client.prepareGet("http://example.com")
.execute()
.toCompletableFuture();
Response response = future.get();
System.out.println(response.getResponseBody());
client.close();
- Performing an asynchronous POST request:
AsyncHttpClient client = Dsl.asyncHttpClient();
client.preparePost("http://example.com/api")
.setBody("{\"key\":\"value\"}")
.setHeader("Content-Type", "application/json")
.execute(new AsyncCompletionHandler<Response>() {
@Override
public Response onCompleted(Response response) throws Exception {
System.out.println("Response: " + response.getResponseBody());
return response;
}
});
client.close();
- Using WebSocket:
AsyncHttpClient client = Dsl.asyncHttpClient();
WebSocket websocket = client.prepareGet("ws://example.com/websocket")
.execute(new WebSocketUpgradeHandler.Builder().addWebSocketListener(
new WebSocketListener() {
@Override
public void onMessage(String message) {
System.out.println("Received message: " + message);
}
}).build()).get();
websocket.sendMessage("Hello, WebSocket!");
client.close();
Getting Started
To use Async Http Client in your project, add the following dependency to your Maven pom.xml:
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>2.12.3</version>
</dependency>
For Gradle, add this to your build.gradle:
implementation 'org.asynchttpclient:async-http-client:2.12.3'
Then, you can start using the client in your Java code:
import org.asynchttpclient.*;
import static org.asynchttpclient.Dsl.*;
AsyncHttpClient client = asyncHttpClient();
// Use the client to make requests
// ...
client.close();
Competitor Comparisons
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
Pros of OkHttp
- Simpler API and easier to use for basic HTTP requests
- Better performance and lower memory footprint
- More active development and frequent updates
Cons of OkHttp
- Less flexible for advanced use cases and custom configurations
- Limited support for WebSocket connections compared to async-http-client
- Fewer built-in features for handling specific scenarios (e.g., OAuth)
Code Comparison
async-http-client:
AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("http://www.example.com/").execute();
Response r = f.get();
OkHttp:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.example.com/")
.build();
Response response = client.newCall(request).execute();
Both libraries offer asynchronous HTTP client functionality for Java applications. async-http-client provides more advanced features and flexibility, making it suitable for complex scenarios. OkHttp, on the other hand, offers a simpler API and better performance for common use cases.
async-http-client excels in scenarios requiring fine-grained control over request execution and handling, while OkHttp is often preferred for its ease of use and efficiency in typical HTTP operations. The choice between the two depends on the specific requirements of your project and the level of control needed over HTTP communications.
A type-safe HTTP client for Android and the JVM
Error generating comparison
Mirror of Apache HttpClient
Pros of httpcomponents-client
- More mature and stable, with a longer history of development
- Extensive documentation and wider community support
- Supports both synchronous and asynchronous operations
Cons of httpcomponents-client
- Generally considered less performant for high-concurrency scenarios
- More verbose API, requiring more code for basic operations
- Heavier dependency footprint
Code Comparison
httpcomponents-client:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("https://api.example.com/data");
CloseableHttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
async-http-client:
AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("https://api.example.com/data").execute();
Response r = f.get();
String result = r.getResponseBody();
The async-http-client code is more concise and focuses on asynchronous operations by default. It provides a more streamlined API for handling HTTP requests and responses. On the other hand, httpcomponents-client offers more flexibility with both synchronous and asynchronous options, but requires more boilerplate code for basic operations.
Both libraries are widely used and have their strengths. The choice between them often depends on specific project requirements, performance needs, and developer preferences.
Vert.x is a tool-kit for building reactive applications on the JVM
Pros of vert.x
- More comprehensive toolkit for building reactive applications
- Supports multiple programming languages (polyglot)
- Better suited for building full-stack applications
Cons of vert.x
- Steeper learning curve due to its broader scope
- May be overkill for simple HTTP client needs
- Larger footprint and potentially higher resource usage
Code Comparison
vert.x HTTP client example:
WebClient client = WebClient.create(vertx);
client.get(8080, "localhost", "/")
.send(ar -> {
if (ar.succeeded()) {
System.out.println("Got response: " + ar.result().bodyAsString());
} else {
System.out.println("Error: " + ar.cause().getMessage());
}
});
async-http-client example:
AsyncHttpClient client = Dsl.asyncHttpClient();
client.prepareGet("http://localhost:8080/")
.execute(new AsyncCompletionHandler<Response>() {
@Override
public Response onCompleted(Response response) {
System.out.println("Got response: " + response.getResponseBody());
return response;
}
});
Both libraries provide asynchronous HTTP client functionality, but vert.x offers a more comprehensive toolkit for building reactive applications across multiple languages. async-http-client is more focused on providing a simple, efficient HTTP client for Java. vert.x may be better suited for larger, more complex projects, while async-http-client might be preferable for simpler use cases or when a lightweight HTTP client is needed.
RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
Pros of RxJava
- Comprehensive reactive programming framework with a wide range of operators
- Supports multiple programming paradigms (functional, declarative, reactive)
- Excellent for handling complex asynchronous operations and event streams
Cons of RxJava
- Steeper learning curve due to its extensive API and concepts
- Can be overkill for simple HTTP requests or basic asynchronous operations
- Potential for memory leaks if not used correctly (e.g., unsubscribed Observables)
Code Comparison
RxJava example:
Observable.just("https://api.example.com/data")
.flatMap(url -> Observable.fromCallable(() -> makeHttpRequest(url)))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> handleResponse(response), error -> handleError(error));
async-http-client example:
AsyncHttpClient client = new AsyncHttpClient();
client.prepareGet("https://api.example.com/data")
.execute(new AsyncCompletionHandler<Response>() {
@Override
public Response onCompleted(Response response) throws Exception {
handleResponse(response);
return response;
}
});
Summary
RxJava is a powerful reactive programming library that excels in handling complex asynchronous operations and event streams. It offers a wide range of operators and supports multiple programming paradigms. However, it has a steeper learning curve and may be excessive for simple HTTP requests.
async-http-client, on the other hand, is more focused on providing asynchronous HTTP client functionality. It's simpler to use for basic HTTP operations but lacks the extensive reactive programming features of RxJava.
Choose RxJava for complex reactive programming needs, and async-http-client for straightforward asynchronous HTTP requests.
Spring Framework
Pros of Spring Framework
- Comprehensive ecosystem with extensive features for web development, data access, and more
- Strong community support and regular updates
- Seamless integration with other Spring projects and third-party libraries
Cons of Spring Framework
- Steeper learning curve due to its extensive feature set
- Can be considered "heavyweight" for smaller projects
- Configuration can be complex, especially for beginners
Code Comparison
Spring Framework (HTTP request):
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("https://api.example.com/data", String.class);
Async HTTP Client:
AsyncHttpClient client = Dsl.asyncHttpClient();
Future<Response> f = client.prepareGet("https://api.example.com/data").execute();
Response r = f.get();
Summary
Spring Framework is a comprehensive Java application framework, while Async HTTP Client is specifically focused on asynchronous HTTP requests. Spring Framework offers a wider range of features and integrations but may be overkill for simple projects. Async HTTP Client provides a more lightweight solution for handling HTTP requests asynchronously, which can be beneficial for performance-critical applications. The choice between the two depends on the project's specific requirements and complexity.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Async Http Client
AsyncHttpClient (AHC) is a high-performance, asynchronous HTTP client for Java built on top of Netty. It supports HTTP/1.1, HTTP/2, and WebSocket protocols.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- HTTP Requests
- Handling Responses
- HTTP/2
- WebSocket
- Authentication
- Proxy Support
- Community
- License
Features
- HTTP/2 with multiplexing â enabled by default over TLS via ALPN, with connection multiplexing and GOAWAY handling
- HTTP/1.1 and HTTP/1.0 â connection pooling and keep-alive
- WebSocket â text, binary, and ping/pong frame support
- Asynchronous API â non-blocking I/O with
ListenableFutureandCompletableFuture - Compression â automatic gzip, deflate, Brotli, and Zstd decompression
- Authentication â Basic, Digest, NTLM, SPNEGO/Kerberos, and SCRAM-SHA-256
- Proxy â HTTP, SOCKS4, and SOCKS5 with CONNECT tunneling
- Native transports â optional Epoll, KQueue, and io_uring
- Request/response filters â intercept and transform at each stage
- Cookie management â RFC 6265-compliant cookie store
- Multipart uploads â file, byte array, input stream, and string parts
- Resumable downloads â built-in
ResumableIOExceptionFilter
Requirements
Java 11+
Installation
Maven:
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>3.0.11</version>
</dependency>
Gradle:
implementation 'org.asynchttpclient:async-http-client:3.0.11'
Optional: Native Transport
For lower-latency I/O on Linux, add a native transport dependency:
<!-- Epoll (Linux) -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-x86_64</classifier>
</dependency>
<!-- io_uring (Linux) -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-io_uring</artifactId>
<classifier>linux-x86_64</classifier>
</dependency>
Then enable in config:
AsyncHttpClient client = asyncHttpClient(config().setUseNativeTransport(true));
Optional: Brotli / Zstd Compression
<dependency>
<groupId>com.aayushatharva.brotli4j</groupId>
<artifactId>brotli4j</artifactId>
<version>1.20.0</version>
</dependency>
<dependency>
<groupId>com.github.luben</groupId>
<artifactId>zstd-jni</artifactId>
<version>1.5.7-7</version>
</dependency>
Quick Start
Import the DSL helpers:
import static org.asynchttpclient.Dsl.*;
Create a client, execute a request, and read the response:
try (AsyncHttpClient client = asyncHttpClient()) {
// Asynchronous
client.prepareGet("https://www.example.com/")
.execute()
.toCompletableFuture()
.thenApply(Response::getResponseBody)
.thenAccept(System.out::println)
.join();
// Synchronous (blocking)
Response response = client.prepareGet("https://www.example.com/")
.execute()
.get();
}
Note:
AsyncHttpClientinstances are long-lived, shared resources. Always close them when done. Creating a new client per request will degrade performance due to repeated thread pool and connection pool creation.
Configuration
Use config() to build an AsyncHttpClientConfig:
AsyncHttpClient client = asyncHttpClient(config()
.setConnectTimeout(Duration.ofSeconds(5))
.setRequestTimeout(Duration.ofSeconds(30))
.setMaxConnections(500)
.setMaxConnectionsPerHost(100)
.setFollowRedirect(true)
.setMaxRedirects(5)
.setCompressionEnforced(true));
HTTP Requests
Sending Requests
Bound â build directly from the client:
Response response = client
.prepareGet("https://api.example.com/users")
.addHeader("Accept", "application/json")
.addQueryParam("page", "1")
.execute()
.get();
Unbound â build standalone via DSL, then execute:
Request request = get("https://api.example.com/users")
.addHeader("Accept", "application/json")
.addQueryParam("page", "1")
.build();
Response response = client.executeRequest(request).get();
Methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE.
Request Bodies
Use setBody to attach a body. Supported types:
| Type | Description |
|---|---|
String | Text content |
byte[] | Raw bytes |
ByteBuffer | NIO buffer |
InputStream | Streaming input |
File | File content |
Publisher<ByteBuf> | Reactive stream |
BodyGenerator | Custom body generation |
Response response = client
.preparePost("https://api.example.com/data")
.setHeader("Content-Type", "application/json")
.setBody("{\"name\": \"value\"}")
.execute()
.get();
For streaming bodies, see FeedableBodyGenerator which lets you push chunks
asynchronously.
Multipart Uploads
Response response = client
.preparePost("https://api.example.com/upload")
.addBodyPart(new FilePart("file", new File("report.pdf"), "application/pdf"))
.addBodyPart(new StringPart("description", "Monthly report"))
.execute()
.get();
Part types: FilePart, ByteArrayPart, InputStreamPart, StringPart.
Handling Responses
Blocking
Response response = client.prepareGet("https://www.example.com/").execute().get();
Useful for debugging, but defeats the purpose of an async client in production.
ListenableFuture
execute() returns a ListenableFuture that supports completion listeners:
ListenableFuture<Response> future = client
.prepareGet("https://www.example.com/")
.execute();
future.addListener(() -> {
Response response = future.get();
System.out.println(response.getStatusCode());
}, executor);
If
executorisnull, the callback runs on the Netty I/O thread. Never block inside I/O thread callbacks.
CompletableFuture
client.prepareGet("https://www.example.com/")
.execute()
.toCompletableFuture()
.thenApply(Response::getResponseBody)
.thenAccept(System.out::println)
.join();
AsyncCompletionHandler
For most async use cases, extend AsyncCompletionHandler â it buffers the
full response and gives you a single onCompleted(Response) callback:
client.prepareGet("https://www.example.com/")
.execute(new AsyncCompletionHandler<String>() {
@Override
public String onCompleted(Response response) {
return response.getResponseBody();
}
});
AsyncHandler
For fine-grained control, implement AsyncHandler directly. This lets you
inspect status, headers, and body chunks as they arrive and abort early:
Future<Integer> future = client
.prepareGet("https://www.example.com/")
.execute(new AsyncHandler<>() {
private int status;
@Override
public State onStatusReceived(HttpResponseStatus s) {
status = s.getStatusCode();
return State.CONTINUE;
}
@Override
public State onHeadersReceived(HttpHeaders headers) {
return State.CONTINUE;
}
@Override
public State onBodyPartReceived(HttpResponseBodyPart part) {
return State.ABORT; // stop early â we only needed the status
}
@Override
public Integer onCompleted() {
return status;
}
@Override
public void onThrowable(Throwable t) {
t.printStackTrace();
}
});
HTTP/2
HTTP/2 is enabled by default for HTTPS connections via ALPN negotiation. The client uses HTTP/2 when the server supports it and falls back to HTTP/1.1 otherwise. No additional configuration is required.
- Connection multiplexing â concurrent streams over a single TCP connection
- GOAWAY handling â graceful connection draining on server shutdown
- PING keepalive â configurable ping frames to keep connections alive
HTTP/2 Configuration
AsyncHttpClient client = asyncHttpClient(config()
.setHttp2MaxConcurrentStreams(100)
.setHttp2InitialWindowSize(65_535)
.setHttp2MaxFrameSize(16_384)
.setHttp2MaxHeaderListSize(8_192)
.setHttp2PingInterval(Duration.ofSeconds(30)) // keepalive pings
.setHttp2CleartextEnabled(true)); // h2c prior knowledge
To force HTTP/1.1, disable HTTP/2:
AsyncHttpClient client = asyncHttpClient(config().setHttp2Enabled(false));
WebSocket
WebSocket ws = client
.prepareGet("wss://echo.example.com/")
.execute(new WebSocketUpgradeHandler.Builder()
.addWebSocketListener(new WebSocketListener() {
@Override
public void onOpen(WebSocket ws) {
ws.sendTextFrame("Hello!");
}
@Override
public void onTextFrame(String payload, boolean finalFragment, int rsv) {
System.out.println(payload);
}
@Override
public void onClose(WebSocket ws, int code, String reason) {}
@Override
public void onError(Throwable t) { t.printStackTrace(); }
})
.build())
.get();
Authentication
// Client-wide Basic auth
AsyncHttpClient client = asyncHttpClient(config()
.setRealm(basicAuthRealm("user", "password")));
// Per-request Digest auth
Response response = client
.prepareGet("https://api.example.com/protected")
.setRealm(digestAuthRealm("user", "password").build())
.execute()
.get();
// SCRAM-SHA-256 (RFC 7804)
Response response = client
.prepareGet("https://api.example.com/protected")
.setRealm(scramSha256AuthRealm("user", "password").build())
.execute()
.get();
Supported schemes: Basic, Digest, NTLM, SPNEGO/Kerberos, SCRAM-SHA-256.
Proxy Support
// HTTP proxy
AsyncHttpClient client = asyncHttpClient(config()
.setProxyServer(proxyServer("proxy.example.com", 8080)));
// Authenticated proxy
AsyncHttpClient client = asyncHttpClient(config()
.setProxyServer(proxyServer("proxy.example.com", 8080)
.setRealm(basicAuthRealm("proxyUser", "proxyPassword"))));
SOCKS4 and SOCKS5 proxies are also supported.
Community
- GitHub Discussions â questions, ideas, and general discussion
- Issue Tracker â bug reports and feature requests
License
Top Related Projects
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
A type-safe HTTP client for Android and the JVM
Mirror of Apache HttpClient
Vert.x is a tool-kit for building reactive applications on the JVM
RxJava – Reactive Extensions for the JVM – a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
Spring Framework
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot