This example demonstrates the WebTransport API structure in Forge.
WebTransport is a new web API that provides low-latency, bidirectional, client-server messaging using HTTP/3 as the transport protocol. It offers several advantages over WebSockets:
- Lower latency: Uses QUIC protocol (UDP-based)
- Multiple streams: Supports multiple independent streams
- Datagrams: Unreliable, unordered message delivery for time-sensitive data
- Better congestion control: QUIC's built-in congestion control
- Connection migration: Survives network changes
- ✅ Bidirectional streams
- ✅ Unidirectional streams
- ✅ Datagram support
- ✅ Multiple concurrent streams
- ✅ HTTP/3 transport
- ✅ TLS 1.3 required
go get github.com/quic-go/quic-go
go get github.com/quic-go/webtransport-gocd v2/examples/webtransport
go run main.goThe server will start on:
- HTTP:
http://localhost:8080
Note: This is a reference implementation showing the WebTransport API structure. The core WebTransport interfaces and router methods are implemented in v2/internal/router/webtransport.go. Full end-to-end support requires HTTP/3 server integration with the main app lifecycle.
-
Core Interfaces (
v2/internal/router/webtransport.go)WebTransportSessioninterfaceWebTransportStreaminterface- Session and stream wrappers
-
Router Integration (
v2/internal/router/router_webtransport.go)router.WebTransport()methodrouter.EnableWebTransport()configurationrouter.StartHTTP3()server managementrouter.StopHTTP3()cleanup
-
Configuration
WebTransportConfigwith sensible defaults- Route options (
WithWebTransport,WithWebTransportDatagrams,WithWebTransportStreams) - Integration with
StreamConfig
-
Tests
- Interface tests
- Configuration tests
- Route option tests
- HTTP/3 server lifecycle integration with
app.Run() - Certificate management helpers
- Full end-to-end example with running server
package main
import (
"github.com/xraph/forge"
"github.com/xraph/forge/extensions/streaming"
)
func main() {
config := forge.DefaultAppConfig()
config.Name = "webtransport-server"
app := forge.NewApp(config)
// Register streaming extension
app.RegisterExtension(streaming.NewExtension(
streaming.WithLocalBackend(),
))
router := app.Router()
// Enable WebTransport
wtConfig := forge.DefaultWebTransportConfig()
router.EnableWebTransport(wtConfig)
// Register WebTransport handler
router.WebTransport("/wt/chat", handleChat)
// Start app (HTTP/3 server starts automatically)
app.Run()
}
func handleChat(ctx forge.Context, session forge.WebTransportSession) error {
// Accept and handle streams
stream, _ := session.AcceptStream(ctx.Context())
// Read/write data
data := make([]byte, 4096)
n, _ := stream.Read(data)
stream.Write(data[:n])
// Send/receive datagrams
session.SendDatagram([]byte("fast message"))
msg, _ := session.ReceiveDatagram(ctx.Context())
return nil
}// Connect to WebTransport server
const url = 'https://localhost:4433/wt/chat';
const transport = new WebTransport(url);
await transport.ready;
console.log('Connected to WebTransport server');
// Send data via bidirectional stream
const stream = await transport.createBidirectionalStream();
const writer = stream.writable.getWriter();
const reader = stream.readable.getReader();
await writer.write(new TextEncoder().encode('Hello WebTransport!'));
// Read response
const { value, done } = await reader.read();
if (!done) {
console.log('Received:', new TextDecoder().decode(value));
}
// Send datagram (unreliable, fast)
const dgWriter = transport.datagrams.writable.getWriter();
await dgWriter.write(new TextEncoder().encode('Quick message'));
// Close connection
await transport.close();package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"github.com/quic-go/quic-go/http3"
"github.com/quic-go/webtransport-go"
)
func main() {
roundTripper := &http3.RoundTripper{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // For testing only
},
}
defer roundTripper.Close()
rsp, session, err := webtransport.Dial(
context.Background(),
"https://localhost:4433/wt/chat",
roundTripper,
)
if err != nil {
log.Fatal(err)
}
defer session.Close()
// Open bidirectional stream
stream, _ := session.OpenStream()
stream.Write([]byte("Hello!"))
// Send datagram
session.SendDatagram([]byte("Quick ping"))
}type WebTransportConfig struct {
MaxBidiStreams int64 // Default: 100
MaxUniStreams int64 // Default: 100
MaxDatagramFrameSize int64 // Default: 65536 (64KB)
EnableDatagrams bool // Default: true
StreamReceiveWindow uint64 // Default: 6MB
ConnectionReceiveWindow uint64 // Default: 15MB
KeepAliveInterval int // Default: 30000ms
MaxIdleTimeout int // Default: 60000ms
}wtConfig := forge.DefaultWebTransportConfig()
wtConfig.MaxBidiStreams = 200 // Max bidirectional streams
wtConfig.MaxUniStreams = 200 // Max unidirectional streams
wtConfig.EnableDatagrams = true // Enable datagram support
wtConfig.MaxDatagramFrameSize = 65536 // 64KB max datagram size
wtConfig.KeepAliveInterval = 30000 // 30 seconds
wtConfig.MaxIdleTimeout = 60000 // 60 seconds
router.EnableWebTransport(wtConfig)
router.StartHTTP3(":4433", tlsConfig)WebTransport requires TLS 1.3:
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS13,
}// Use datagrams for player position (unreliable, fast)
session.SendDatagram(marshalPosition(player))
// Use streams for chat messages (reliable)
stream, _ := session.OpenStream()
stream.WriteJSON(chatMessage)// Use unidirectional streams for video chunks
stream, _ := session.OpenUniStream()
for chunk := range videoChunks {
stream.Write(chunk)
}// Use datagrams for stock prices (latest value only)
session.SendDatagram(marshalStockPrice(symbol, price))
// Use streams for order confirmations (reliable)
stream.WriteJSON(orderConfirmation)| Feature | Streams | Datagrams |
|---|---|---|
| Reliability | Reliable, ordered | Unreliable, unordered |
| Use case | Chat, file transfer | Gaming, live data |
| Latency | Higher | Lower |
| Ordering | Guaranteed | Not guaranteed |
WebTransport is supported in:
- Chrome 97+
- Edge 97+
- Opera 83+
Check current support: Can I use WebTransport
- Use datagrams for time-sensitive data: Stock prices, player positions
- Use streams for critical data: Chat messages, file transfers
- Reuse streams: Opening streams has overhead
- Batch small messages: Combine multiple small messages
- Monitor congestion: QUIC provides built-in congestion control
| Feature | WebTransport | WebSocket |
|---|---|---|
| Protocol | HTTP/3 (QUIC/UDP) | HTTP/1.1 or HTTP/2 (TCP) |
| Latency | Lower | Higher |
| Streams | Multiple independent | Single stream |
| Head-of-line blocking | No | Yes (TCP) |
| Datagrams | Yes | No |
| Browser support | Limited | Wide |
v2/internal/router/webtransport.go- Core interfaces and wrappersv2/internal/router/router_webtransport.go- Router integrationv2/internal/router/router_webtransport_opts.go- Route optionsv2/internal/router/webtransport_test.go- Testsv2/internal/router/streaming.go- StreamConfig with WT support
- WebTransport Specification
- QUIC Protocol
- HTTP/3 Specification
- WebTransport API
- quic-go Documentation
Part of the Forge framework.