Skip to content

Commit 5ed3db1

Browse files
committed
docs: add WebTransport over HTTP/3 reference page
1 parent aec7a7a commit 5ed3db1

2 files changed

Lines changed: 168 additions & 0 deletions

File tree

docs/astro.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export default defineConfig({
9696
{ label: 'Core Runtime', slug: 'reference/core' },
9797
{ label: 'Rooms & Presence', slug: 'reference/rooms' },
9898
{ label: 'MCP Server', slug: 'reference/mcp' },
99+
{ label: 'WebTransport/HTTP3', slug: 'reference/webtransport' },
99100
{ label: 'gRPC Transport', slug: 'reference/grpc' },
100101
{ label: 'Kotlin DSL', slug: 'reference/kotlin' },
101102
{ label: 'Observability', slug: 'reference/observability' },
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
title: "WebTransport over HTTP/3"
3+
description: "Bidirectional streaming via QUIC — first Java framework with WebTransport"
4+
---
5+
6+
# WebTransport over HTTP/3
7+
8+
Bidirectional streaming transport for Atmosphere using WebTransport over HTTP/3 (QUIC). The first Java framework with WebTransport support. Browsers connect over QUIC with multiplexed streams, built-in congestion control, and sub-millisecond latency — with automatic fallback to WebSocket.
9+
10+
## How It Works
11+
12+
The WebTransport server runs as a **Spring-managed sidecar** alongside the servlet container on a separate UDP port. Both transports feed into the same Atmosphere framework — your application code doesn't change. An `Alt-Svc` header tells browsers that HTTP/3 is available.
13+
14+
```
15+
Spring Boot App
16+
+----------------------------------+----------------------------+
17+
| Servlet Container (Jetty/Tomcat) | Netty HTTP/3 (UDP sidecar) |
18+
| HTTP/1.1, HTTP/2, WebSocket | HTTP/3, WebTransport |
19+
+----------------+-----------------+-------------+--------------+
20+
| |
21+
v v
22+
AtmosphereFramework (doCometSupport / WebSocketProcessor)
23+
|
24+
@Agent / @Prompt / @ManagedService / Handlers
25+
```
26+
27+
## Quick Start
28+
29+
### 1. Add the dependency
30+
31+
```xml
32+
<dependency>
33+
<groupId>io.projectreactor.netty</groupId>
34+
<artifactId>reactor-netty-http</artifactId>
35+
</dependency>
36+
```
37+
38+
This is managed by Spring Boot's BOM — no version needed.
39+
40+
### 2. Enable in application.yml
41+
42+
```yaml
43+
atmosphere:
44+
web-transport:
45+
enabled: true
46+
port: 4443
47+
```
48+
49+
The HTTP/3 server starts automatically with a self-signed ECDSA certificate for development. The certificate hash is exposed at `/api/webtransport-info`.
50+
51+
### 3. Connect from JavaScript
52+
53+
```typescript
54+
import { Atmosphere } from 'atmosphere.js';
55+
56+
const atmosphere = new Atmosphere();
57+
58+
// Fetch cert hash for dev self-signed cert
59+
const info = await (await fetch('/api/webtransport-info')).json();
60+
61+
const subscription = await atmosphere.subscribe({
62+
url: '/atmosphere/chat',
63+
transport: 'webtransport',
64+
fallbackTransport: 'websocket',
65+
webTransportUrl: `https://${location.hostname}:${info.port}/atmosphere/chat`,
66+
serverCertificateHashes: [info.certificateHash],
67+
}, {
68+
open: () => console.log('Connected via WebTransport!'),
69+
message: (response) => console.log(response.responseBody),
70+
});
71+
```
72+
73+
In production behind a reverse proxy with real TLS, omit `webTransportUrl` and `serverCertificateHashes` — both protocols share the same origin.
74+
75+
## Configuration
76+
77+
| Property | Default | Description |
78+
|----------|---------|-------------|
79+
| `atmosphere.web-transport.enabled` | `false` | Enable the HTTP/3 sidecar server |
80+
| `atmosphere.web-transport.port` | `4443` | UDP port for QUIC/HTTP/3 |
81+
| `atmosphere.web-transport.host` | `0.0.0.0` | Bind address |
82+
| `atmosphere.web-transport.add-alt-svc` | `true` | Add `Alt-Svc` header to servlet responses |
83+
| `atmosphere.web-transport.ssl.certificate` | (auto) | Path to PEM certificate file |
84+
| `atmosphere.web-transport.ssl.private-key` | (auto) | Path to PEM private key file |
85+
86+
## Production Deployment
87+
88+
Use a reverse proxy (nginx, Cloudflare, Caddy) that terminates both HTTP/2 (TCP) and HTTP/3 (QUIC) on the same hostname:port:
89+
90+
```nginx
91+
server {
92+
listen 443 ssl http2;
93+
listen 443 quic reuseport;
94+
95+
ssl_certificate /path/to/cert.pem;
96+
ssl_certificate_key /path/to/key.pem;
97+
98+
add_header Alt-Svc 'h3=":443"; ma=86400';
99+
100+
location / {
101+
proxy_pass http://localhost:8080;
102+
proxy_http_version 1.1;
103+
proxy_set_header Upgrade $http_upgrade;
104+
proxy_set_header Connection "upgrade";
105+
}
106+
}
107+
```
108+
109+
## Browser Support
110+
111+
| Browser | Version | Coverage |
112+
|---------|---------|----------|
113+
| Chrome | 97+ | Jan 2022 |
114+
| Edge | 98+ | Feb 2022 |
115+
| Firefox | 114+ | Jun 2023 |
116+
| Safari | 26.4+ | 2026 |
117+
| Opera | 83+ | Mar 2022 |
118+
119+
~80% global coverage. The `fallbackTransport: 'websocket'` setting ensures all browsers work.
120+
121+
## Architecture
122+
123+
The server uses raw Netty HTTP/3 codec (not Reactor Netty's HttpServer) because WebTransport requires protocol features not exposed by Reactor Netty:
124+
125+
- **`ENABLE_CONNECT_PROTOCOL`** (RFC 9220) — extended CONNECT method
126+
- **`H3_DATAGRAM`** (RFC 9297) — QUIC datagram support
127+
- **`WEBTRANSPORT_MAX_SESSIONS`** — session negotiation (draft-02 + draft-07)
128+
- **WebTransport frame type `0x41`** — bidirectional data streams
129+
130+
Sessions bridge into Atmosphere via `WebSocketProcessor.open()`, the same pattern used by JSR 356 WebSocket.
131+
132+
## Client API
133+
134+
The `WebTransportTransport` in atmosphere.js supports all standard `BaseTransport` features:
135+
136+
- Automatic reconnection with exponential backoff
137+
- Protocol handshake and heartbeat
138+
- Message tracking and length-delimited framing
139+
- Outgoing/incoming interceptors
140+
- Offline queue with drain-on-reconnect
141+
- `suspend()` / `resume()` for pausing without disconnect
142+
143+
New request options:
144+
145+
| Option | Type | Description |
146+
|--------|------|-------------|
147+
| `webTransportUrl` | `string` | Explicit URL for the HTTP/3 server (dev mode) |
148+
| `serverCertificateHashes` | `string[]` | Base64 SHA-256 cert hashes for self-signed certs |
149+
150+
## SPI
151+
152+
The `org.atmosphere.webtransport` package provides a transport-agnostic SPI:
153+
154+
| Class | Purpose |
155+
|-------|---------|
156+
| `WebTransportSession` | Abstract bidirectional stream session |
157+
| `WebTransportHandler` | Application-level callbacks |
158+
| `WebTransportProcessor` | Processing SPI |
159+
| `WebTransportProtocol` | Message-to-request conversion |
160+
| `WebTransportEventListener` | Lifecycle events |
161+
162+
## Limitations (v1)
163+
164+
- Single bidirectional stream per session (WebSocket-equivalent semantics)
165+
- QUIC datagrams not yet exposed to application code
166+
- Multiplexed streams deferred to v2
167+
- Chrome strips query params from WebTransport CONNECT `:path` — auth tokens must use header-based authentication, not query parameters

0 commit comments

Comments
 (0)