Zurück zum Ranking

AsyncHttpClient/async-http-client

Java

Asynchronous, non-blocking HTTP & WebSocket client for the JVM

nettyasyncjavaasynchttpclientahchttp-client
Sterne-Wachstum
Sterne
6.4k
Forks
1.6k
Wochenwachstum
Issues
93
2k4k6k
März 2011Apr. 2016Juni 2021Juli 2026
ArtefakteMavengit clone https://github.com/AsyncHttpClient/async-http-client.git
README

Async Http Client

Build Maven Central License

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

  • 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 ListenableFuture and CompletableFuture
  • 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: AsyncHttpClient instances 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 executor is null, 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

License

Apache License 2.0

Ähnliche Repositories
crossoverJie/JCSprout

👨‍🎓 Java Core Sprout : basic, concurrent, algorithm

JavaMavenMIT Licensejavaconcurrent-programming
crossoverjie.top/JCSprout
26.9k7k
doocs/source-code-hunter

😱 从源码层面,剖析挖掘互联网行业主流技术的底层实现原理,为广大开发者 “提升技术深度” 提供便利。目前开放 Spring 全家桶,Mybatis、Netty、Dubbo 框架,及 Redis、Tomcat 中间件等

JavaMavenCreative Commons Attribution Share Alike 4.0 Internationalsourcecode-analysisspring
schunter.doocs.org
23.1k4.2k
eclipse-vertx/vert.x

Vert.x is a tool-kit for building reactive applications on the JVM

JavaMavenOthervertxjava
vertx.io
14.7k2.1k
crossoverJie/cim

📲cim(cross IM) 适用于开发者的分布式即时通讯系统

JavaMavenMIT Licensenettytcp
crossoverjie.top/categories/Netty/
9.5k2.9k
mrniko/netty-socketio

Socket.IO server implemented on Java. Realtime java framework

JavaMavenApache License 2.0socket-iojava
7k1.7k
gatling/gatling

Modern Load Testing as Code

ScalaApache License 2.0nettyscala
gatling.io
6.9k1.2k
jetlinks/jetlinks-community

JetLinks 基于Java,Spring Boot ,WebFlux,Netty,Vert.x,Reactor等开发, 是一个全响应式的企业级物联网平台。支持统一物模型管理,多种设备,多种厂家,统一管理。统一设备连接管理,多协议适配(TCP,MQTT,UDP,CoAP,HTTP等),屏蔽网络编程复杂性,灵活接入不同厂家不同协议等设备。实时数据处理,设备告警,消息通知,数据转发。地理位置,数据可视化等。能帮助你快速建立物联网相关业务系统。

JavaMavenApache License 2.0iotjava
jetlinks.cn
6.5k1.9k
JackJiang2011/MobileIMSDK

原创全平台IM通信层框架,轻量级、高度提炼,历经10年、久经考验。可能是市面上唯一同时支持UDP+TCP+WebSocket三种协议的同类开源框架,支持 iOS、Android、Java、H5、小程序、Uniapp、鸿蒙Next,服务端基于Netty。

Objective-CApache License 2.0imudp
52im.net/forum-89-1.html
6.1k1.4k
line/armeria

Your go-to microservice framework for any situation, from the creator of Netty et al. You can build any type of microservice leveraging your favorite technologies, including gRPC, Thrift, Kotlin, Retrofit, Reactive Streams, Spring Boot and Dropwizard.

JavaMavenApache License 2.0httphttp2
armeria.dev
5.1k1k
helidon-io/helidon

Java libraries for writing microservices

JavaMavenApache License 2.0javamicroservice-framework
helidon.io
3.8k605
mpusher/mpush

MPush开源实时消息推送系统

JavaMavenApache License 2.0pushnetty
mpusher.github.io
3.8k1.4k
sanshengshui/netty-learning-example

:egg: Netty实践学习案例,见微知著!带着你的心,跟着教程。我相信你行欧。

JavaMavenApache License 2.0nettyhttp
2.9k808