Files

2.7 KiB

http3 — HTTP/3 in the Java HTTP Client (JEP 517, final in Java 26)

Companion code for the ankurm.com article HTTP/3 in the Java HTTP Client (JEP 517): Migrating from HttpClient 11. All explanation lives in the article; this folder holds the runnable sources, a local HTTP/3 test server, and the transcripts they produced.

What was tested against

Thing Version Note
JDK 26 Temurin 26.0.2.1+1 JEP 517 is delivered in 26 (GA 2026-03-17); this is the only JDK that can run HTTP/3 here
JDK 25 Temurin 25.0.4.1+1 the "before": HttpClient.Version.HTTP_3 does not exist, plain Java 11 code behaves the same as on 26
Test server Hypercorn 0.18.0 (HTTP/1.1 + HTTP/2 on TCP) + aioquic 1.3.0 (HTTP/3 on UDP) one Python process, same port number for both, Alt-Svc advertised. Hypercorn's own QUIC listener was dropped: it died on a KeyError under packet loss and the port went silent
Loss injection iptables -m statistic --mode random on lo not tc netem (unavailable in the sandbox: Specified qdisc kind is unknown): loss only, no added delay

The JDK 26 lane in the other modules of this repo uses Amazon Corretto 26.0.2.1; this module used Temurin because that is what the sandbox had. The API is the same.

Quickstart

pip install hypercorn==0.18.0 aioquic==1.3.0
JDK25=/path/to/jdk-25 JDK26=/path/to/jdk-26 ./run.sh        # about 45 minutes: the `HTTP_3_URI_ONLY` failure demos wait a full minute each and the loss table is 600 trials; needs root for 05 and 07; ONLY=07 regenerates just the loss table
# or by hand:
./server/make-cert.sh && python3 server/serve.py h3 4433 &  # h3 | h2 | h1
java src/OptIn.java https://localhost:4433/hello request

Layout

Path What is in it
src/Tls.java trusts only the self-signed test certificate
src/Basics.java plain Java 11 HttpClient code, no version set
src/OptIn.java the JEP 517 opt-in, client-wide or per request
src/Discovery.java the three H3_DISCOVERY modes
src/Fallback.java first-request latency and version for each way of asking, against servers that cannot do HTTP/3
src/ViaProxy.java HTTP/3 and a proxy
src/Bench.java HTTP/1.1 vs HTTP/2 vs HTTP/3 download times under packet loss
server/ app.py (shared responses + ASGI wrapper), serve.py (h3 / h2 / h1 modes), h3server.py (aioquic HTTP/3), connect-proxy.py, make-cert.sh
scripts/loss.sh adds and removes the iptables loss rules and the MTU change
output/ every transcript quoted in the article (01-08)

Timings are machine dependent and the loss is random: treat 07-packet-loss.txt as shape, not a benchmark of HTTP/3 implementations. The server is Python, the client is the JDK.