---
url: /httpx.zig/examples/http3-quic.md
---
# Example: Http3 Quic

Demonstrates http3Quic.zig using the canonical HTTPX API.

## Complete Example

```zig
//! HTTP/3 & QUIC Transport Engine Example.
//!
//! Demonstrates:
//! 1. QUIC Packet construction, Variable-length integer encoding (RFC 9000)
//! 2. QUIC Frame serialization (STREAM, ACK, CRYPTO, CONNECTION_CLOSE)
//! 3. QPACK dynamic table encoder/decoder operations (RFC 9204)
//! 4. Full HTTP/3 control & request stream multiplexing (RFC 9114)
//! Run with: `zig build run-http3-quic`

const std = @import("std");
const httpx = @import("httpx");

pub fn main() !void {
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    std.debug.print("=== HTTP/3 & QUIC Protocol Engine ===\n", .{});

    // 1. QUIC Variable-Length Integer Encoding (RFC 9000 Section 16)
    var varint_buf: [16]u8 = undefined;
    const test_values = [_]u62{ 25, 15293, 494878333, 1512888099419124471 };
    std.debug.print("1. QUIC Varint Encoding:\n", .{});
    for (test_values) |val| {
        const n = try httpx.quic.varint.encode(&varint_buf, val);
        var off: usize = 0;
        const decoded_val = try httpx.quic.varint.decode(varint_buf[0..n], &off);
        std.debug.print("   Value {d} -> encoded {d} bytes, decoded {d}\n", .{ val, n, decoded_val });
    }

    // 2. QUIC Frame Construction (RFC 9000 section 12.4) - using clean wrapper
    var frame = try httpx.quic.encodeFrame(allocator, .{
        .stream = .{
            .id = 4,
            .offset = 0,
            .data = "HTTP/3 over QUIC binary stream",
            .fin = true,
        },
    });
    defer frame.deinit(allocator);
    std.debug.print("2. Encoded QUIC STREAM Frame (Stream 4, FIN=true) -> {d} bytes\n", .{frame.items.len});

    // 3. QPACK Dynamic Table Encoding (RFC 9204)
    var qenc = httpx.http3.qpack.Encoder.init(allocator);
    defer qenc.deinit();
    var qdec = httpx.http3.qpack.Decoder.init(allocator);
    defer qdec.deinit();

    var field_section = std.ArrayList(u8).empty;
    defer field_section.deinit(allocator);

    // Required Insert Count & Delta Base prefix
    try field_section.appendSlice(allocator, "\x00\x00");
    try qenc.encodeField(&field_section, ":method", "GET");
    try qenc.encodeField(&field_section, ":path", "/index.html");
    try qenc.encodeField(&field_section, ":scheme", "https");
    try qenc.encodeField(&field_section, ":authority", "quic.example.org");
    try qenc.encodeField(&field_section, "x-quic-version", "v1");

    std.debug.print("3. QPACK encoded 5 HTTP/3 headers into {d} bytes\n", .{field_section.items.len});

    // 4. HTTP/3 Client-Server Connection Lifecycle
    var client_conn = httpx.http3.Connection.init(allocator, .client);
    defer client_conn.deinit();
    var server_conn = httpx.http3.Connection.init(allocator, .server);
    defer server_conn.deinit();

    const client_ctrl = try client_conn.buildControlStream();
    defer allocator.free(client_ctrl);

    var off: usize = 1;
    const parsed_frame = try httpx.http3.frame.parseFrame(client_ctrl, &off);
    try server_conn.processControlFrame(parsed_frame.frameType, parsed_frame.payload);

    const bidi_id = client_conn.nextBidiStreamId();
    var req_stream = client_conn.createRequestStream(bidi_id);

    const req_headers = [_]httpx.http3.qpack.FieldLine{
        .{ .name = "user-agent", .value = "httpx-quic-client" },
    };
    const req_bytes = try req_stream.buildRequestHeaders("GET", "https", "quic.example.org", "/", &req_headers);
    defer allocator.free(req_bytes);

    std.debug.print("4. HTTP/3 request stream #{d} constructed: {d} bytes with QPACK\n", .{ bidi_id, req_bytes.len });
    std.debug.print("HTTP/3 & QUIC demonstration completed successfully.\n", .{});
}
```

## How to Run

```bash
zig build run-http3-quic
```

## Related

* [Getting Started](/guide/getting-started)
* [All Examples](/examples/)
