v0.3.3 renamed this to package zap, and that was wrong twice. Go resolves an
unaliased import to the package's own name, so github.com/zap-proto/http should
answer to http; and this package IMPORTS zap, the wire format, so naming itself
zap put two different things under one word in the same file. An importer that
also needs net/http aliases one of them, which is the ordinary convention rather
than a reason to invent a name.
zap.Version and zap.HeaderSize are that other package and are untouched.
Co-authored-by: Hanzo Dev <[email protected]>
zaphttp was a compound word invented to disambiguate a module whose path
already reads github.com/zap-proto/http. The package is the ZAP wire; the
module path says what it speaks. An importer that also needs net/http aliases
one of them, which is the ordinary Go convention rather than a reason to build
a compound name into every file.
The file that carried the name in its own filename is zap_test.go now, for the
same reason: a file is named for what it holds.
Co-authored-by: Hanzo Dev <[email protected]>
The wire was already ZAP binary on both sides; only the plumbing was pinned
to TCP (net.Listen("tcp"), net.DialTimeout("tcp")). Lifting that to a value
mirrors net.Dial/net.Listen — the network is an argument, not a family of
functions — and unix sockets fall out with no change to the frames:
zaphttp.Dial("unix", "/run/hanzo/billing.sock")
&zaphttp.Server{Network: "unix", Addr: "/run/hanzo/billing.sock"}
NewTransport is gone in favour of Dial: it was a compound name for what net
already calls dialing, and keeping both would be two ways to do one thing.
All callers migrated.
Serving on unix clears a stale socket first — a crashed predecessor leaves a
file that bind refuses, so restart-in-place needs it. A socket with something
live behind it still fails, loudly, rather than being unlinked out from under
a running process.
Co-authored-by: Hanzo Dev <[email protected]>
Adds multi-frame streamed responses so SSE / MCP notifications / progress /
chunked bodies ride ZAP as real server→client push, not a buffered blob. A
streamed response is a head frame (status+headers) + N data frames (one per
handler flush) + an end frame — the analogue of HTTP/2 HEADERS+DATA+END_STREAM.
- wire.go: FrameResponseHead/FrameData/FrameEnd + Marshal/Unmarshal + FrameTypeOf.
- server.go: when ctx.Response.IsBodyStream(), stream via BodyWriteTo→chunkWriter
(each flush = one FrameData frame on the wire immediately). Non-stream path
unchanged (single FrameResponse) — fully backward-compatible.
- client.go: Transport.Do dispatches on frame type; a head attaches a streaming
body (streamReader) that reads data frames until end, releasing the pooled conn
only when the stream drains (or closes it if abandoned mid-stream).
Verified: TestStream_SSEOverZAP flushes 3 events one-at-a-time and the client
receives each BEFORE the next is released (a buffering regression would deadlock/
time out — the guard proves real incremental push). All existing round-trip +
keep-alive tests pass; go test -race clean; gofmt clean.