zeekay 5aa0d29f91 perf: zero-alloc ZAP-HTTP codec + pooled server/client hot path
Hand-rolled frame encoder/decoder (codec.go) replaces the zap.Builder +
map[string][]string + json.Marshal path. Wire stays byte-identical (golden
tests + TestCodec_CrossCheck vs a zap.Builder oracle across a wide corpus,
incl. special-char headers). Headers are streamed straight into the frame tail
as compact sorted-key JSON, byte-identical to json.Marshal, with a stdlib
fallback for escape/UTF-8 values; decode scans the JSON in place into the
fasthttp store with a json.Unmarshal fallback.

Server: one RequestCtx per connection (Init2 + per-request Reset) instead of a
per-request heap alloc; reused frame read/write buffers; single-syscall
length-prefixed response write.
Client: per-conn reused request/response buffers, single frame-type peek + one
decode (was double zap.Parse), single-syscall request write.

Codec allocs/op (default GOGC):
  MarshalRequest  11 -> 1 (Append: 0)   MarshalResponse 19 -> 1 (Append: 0)
  UnmarshalResponse 11 -> 0             hot Append/Unmarshal all 0 allocs/op
2026-07-17 01:20:47 -07:00
2026-05-06 13:07:41 -07:00

zap-http

Docs: HTTP over ZAP · part of the ZAP Protocol

HTTP request/response semantics over the ZAP transport.

zap-proto.io · Spec · Paper · Discord

Drop-in replacement for net/http server and client when both peers live in a trusted boundary (in-cluster service mesh, agent-to-tool, edge-to-edge). Existing handlers and http.Client code work unchanged — only the wire underneath changes.

Why

Property net/http over TCP+TLS zap-http
Confidentiality TLS (classical curves) X-Wing hybrid PQ (X25519 + ML-KEM-768)
Authentication bearer / JWT at app layer KEM keypair at transport layer
Wire encoding text headers + chunked body ZAP wire, zero-copy
Field access parse → allocate → copy pointer offset, O(1)
JWT mint per call typical not in the path

Install

go get github.com/zap-proto/http

Requires Go 1.23+.

Server

package main

import (
    "io"
    "net/http"

    zaphttp "github.com/zap-proto/http"
)

func main() {
    http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "ok")
    })
    if err := zaphttp.ListenAndServe(":9999", nil); err != nil {
        panic(err)
    }
}

Same http.Handler, same http.HandleFunc, same default mux. The wire is ZAP-HTTP.

Client

package main

import (
    "io"
    "net/http"
    "os"

    zaphttp "github.com/zap-proto/http"
)

func main() {
    client := &http.Client{Transport: zaphttp.NewTransport("server:9999")}
    resp, err := client.Get("http://server/healthz")
    if err != nil { panic(err) }
    defer resp.Body.Close()
    io.Copy(os.Stdout, resp.Body)
}

http.Client machinery — timeouts, redirects, cookies — keeps working unchanged.

Wire format

Each HTTP message is one ZAP frame, defined in schema/zap_http.zap using the ZAP schema language. Today the wire layer is length-prefixed framing over TCP; the paper and the v0.2 release will swap that for the full ZAP transport with X-Wing PQ KEM handshake on connect.

zap-http v0.1 wire (transitional):
  +---------+-------------------+
  | u32 BE  |   ZAP Frame       |
  | length  |   (zap_http.zap)  |
  +---------+-------------------+

zap-http v0.2 wire:
  +-----------------------------+--------+-----------+
  | ZAP transport (X-Wing KEM,  | AEAD   | ZAP Frame |
  | mutual auth, multi-stream)  | header |           |
  +-----------------------------+--------+-----------+

The .zap schema is the source of truth for what's on the wire. Marshal/unmarshal in any language follows from the schema; bindings:

What's in v0.1

Feature Status
Request method, target, headers, body ✓
Response status, reason, headers, body ✓
Multi-value headers preserved ✓
Trailers (read & write) ✓
http.Client / http.Handler compatibility ✓
Length-prefixed framing over TCP ✓
64 MiB max frame size (configurable) ✓
Streaming bodies (chunked-style) v0.2
Connection pool / keep-alive on client v0.2
Real ZAP transport (PQ KEM handshake) v0.2
WebSocket-style upgrade see zap-proto/ws

Sub-protocol family

  • zap-http — this repo
  • zap-ws — multi-stream pubsub, per-stream FEC
  • zap-fix — FIX 4.4/5.0 trading channel
  • zap-rns — KEM-bound service naming
  • zap-mcp — Model Context Protocol over ZAP
  • zap-acp — Agent Communication Protocol
  • zap-a2a — Google Agent2Agent over ZAP

By the composability theorem, every sub-protocol that embeds onto ZAP-base inherits its post-quantum confidentiality and mutual authentication automatically.

Schema regeneration

make schema    # regenerates internal/wire/zap_http.go from schema/zap_http.zap

Requires zapc (the ZAP schema compiler) on PATH. Build it once from zap-proto/spec:

cargo install --path .   # from a clone of zap-proto/spec

License

MIT OR Apache-2.0

S
Description
HTTP request/response over ZAP — drop-in net/http API
Readme MIT
191 KiB
Languages
Go 93.9%
ZAP 5.7%
Makefile 0.4%