Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KqJyCidz3ZgRyHABv2GVJh
43 lines
2.7 KiB
Markdown
43 lines
2.7 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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.
|