Repository navigation
colibri 0.14.0
colibri 0.14.0 adds colibri, a module that binds the sockets and runs the loop: a program gives colibri.Server a host, a port, a PEM identity and a server.router table, and calls run. It serves h11 and h2 over TCP and h3 over QUIC on the UDP socket of the same port, on Rotor's own loop. The client keeps a response's headers and trailers whole, and an h3 client no longer stops on a status that RFC 9110 does not name. It pins stdx 51c91698, chapulin 965668d2 and Rotor 4f818b7.
Breaking changes
client.Response.wanted,Response.values,Response.values_lenandclient.WantedHeaderare gone (decision 152). A response holds its header section inResponse.headers, aclient.Headers, and its trailer section inResponse.trailers, aclient.Trailers, each over a buffer the program gives. A program reads a value withresponse.headers.get("content-type")and every line withiterator(). An empty buffer drops its section, and a section that does not fit ends the exchangetoo_large.- Rotor is no longer a lazy package: the library's
colibrimodule imports it, so a project that depends on colibri fetches Rotor too. - An h3 request whose stream ended with its head now reports
request.endwith that head, and no emptybodyfollows (decision 116 as amended). A program that reads h3 events itself readsrequest.end;server.routeralready did.
What's new
colibri.Server(decision 150, design §8 step 37):init(config)reads the identity, given as PEM text incolibri.Identity { chain, key }, and binds. The program reads its own files and may wipe the key text afterinit.port()returns the bound port, so a program may ask for port 0.run(router, context)serves on one Rotor loop on the calling thread untilshutdown(), which any thread may call.deinit()closes whatinitopened and wipes the private key and the cookie key.- With an identity, the server opens UDP on the same port for h3, with UDP_GRO and UDP_SEGMENT on Linux, and its TLS connections advertise h3 there (Alt-Svc).
- With no source of randomness given, it draws from the operating system's entropy.
examples/colibri_server.zigserves a route table on 127.0.0.1 port 0.
- An h3 client reads a response's trailers, and h11 and h2 clients read them too, into
Response.trailers.
Fixes
- An h3 client converted a server's status to an enum of RFC 9110's codes, so a 429 (RFC 6585) or a 599 stopped it on an assertion. It now compares the number.
- h11 kept a chunked message's trailer section into the next message, so a message without chunked coding that followed one with trailers reported them again, in the client and the server. h11 now clears it at each head.
Speed
- h3: a request whose stream ended with its head takes one event, not three (design §8 step 29d.15), and a field section that inserts nothing into the QPACK table takes no encoder stream room (step 29d.13).
Checked
tools/ci.sh passed on 8ae5faf1, with Zig 0.16.0 on macOS arm64. As the owner ruled on 2026-11-05, the run left out the TLA+ models and the seven trace checks, which a nightly job will run.