package http — the last element of the module path, as Go expects

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]>
This commit is contained in:
2026-08-10 16:16:08 -07:00
co-authored by Hanzo Dev
parent 6d46bc4941
commit e9ad01194d
10 changed files with 73 additions and 73 deletions
+7 -7
View File
@@ -1,4 +1,4 @@
package zap_test package http_test
// Exported-API-only codec benchmarks. These use only MarshalRequest / // Exported-API-only codec benchmarks. These use only MarshalRequest /
// MarshalResponse / UnmarshalRequest / UnmarshalResponse, so the SAME file // MarshalResponse / UnmarshalRequest / UnmarshalResponse, so the SAME file
@@ -34,7 +34,7 @@ func BenchmarkCompat_MarshalRequest(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, err := zap.MarshalRequest(req); err != nil { if _, err := http.MarshalRequest(req); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -46,7 +46,7 @@ func BenchmarkCompat_MarshalResponse(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if _, err := zap.MarshalResponse(resp); err != nil { if _, err := http.MarshalResponse(resp); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -54,13 +54,13 @@ func BenchmarkCompat_MarshalResponse(b *testing.B) {
func BenchmarkCompat_UnmarshalRequest(b *testing.B) { func BenchmarkCompat_UnmarshalRequest(b *testing.B) {
req := compatReq() req := compatReq()
frame, _ := zap.MarshalRequest(req) frame, _ := http.MarshalRequest(req)
fasthttp.ReleaseRequest(req) fasthttp.ReleaseRequest(req)
var dst fasthttp.Request var dst fasthttp.Request
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if err := zap.UnmarshalRequest(frame, &dst); err != nil { if err := http.UnmarshalRequest(frame, &dst); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
@@ -68,13 +68,13 @@ func BenchmarkCompat_UnmarshalRequest(b *testing.B) {
func BenchmarkCompat_UnmarshalResponse(b *testing.B) { func BenchmarkCompat_UnmarshalResponse(b *testing.B) {
resp := compatResp() resp := compatResp()
frame, _ := zap.MarshalResponse(resp) frame, _ := http.MarshalResponse(resp)
fasthttp.ReleaseResponse(resp) fasthttp.ReleaseResponse(resp)
var dst fasthttp.Response var dst fasthttp.Response
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
if err := zap.UnmarshalResponse(frame, &dst); err != nil { if err := http.UnmarshalResponse(frame, &dst); err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
+12 -12
View File
@@ -2,7 +2,7 @@
// //
// Usage mirrors fasthttp's Do(req, resp): // Usage mirrors fasthttp's Do(req, resp):
// //
// t := zap.Dial("tcp", "server:9999") // t := http.Dial("tcp", "server:9999")
// req := fasthttp.AcquireRequest() // req := fasthttp.AcquireRequest()
// resp := fasthttp.AcquireResponse() // resp := fasthttp.AcquireResponse()
// req.SetRequestURI("/healthz") // req.SetRequestURI("/healthz")
@@ -16,7 +16,7 @@
// decoded — no body-close handshake is needed. The pool caps at // decoded — no body-close handshake is needed. The pool caps at
// MaxIdleConns; surplus conns close on return. // MaxIdleConns; surplus conns close on return.
package zap package http
import ( import (
"bufio" "bufio"
@@ -57,8 +57,8 @@ type Transport struct {
// functions. A unix address is a socket path and carries the same ZAP frames // functions. A unix address is a socket path and carries the same ZAP frames
// as tcp — the wire does not change with the network. // as tcp — the wire does not change with the network.
// //
// zap.Dial("tcp", "billing.hanzo.svc:9653") // http.Dial("tcp", "billing.hanzo.svc:9653")
// zap.Dial("unix", "/run/hanzo/billing.sock") // http.Dial("unix", "/run/hanzo/billing.sock")
// //
// Dialing is lazy; the first request opens the connection. // Dialing is lazy; the first request opens the connection.
func Dial(network, addr string) *Transport { func Dial(network, addr string) *Transport {
@@ -93,12 +93,12 @@ func (t *Transport) SetMaxIdleConns(n int) {
// for concurrent use: each call takes its own connection from the pool. // for concurrent use: each call takes its own connection from the pool.
func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error { func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
if t.addr == "" { if t.addr == "" {
return fmt.Errorf("zap: Transport.addr is empty (use Dial)") return fmt.Errorf("zaphttp: Transport.addr is empty (use Dial)")
} }
pc, err := t.acquireConn() pc, err := t.acquireConn()
if err != nil { if err != nil {
return fmt.Errorf("zap: dial %s: %w", t.addr, err) return fmt.Errorf("zaphttp: dial %s: %w", t.addr, err)
} }
conn, br := pc.c, pc.br conn, br := pc.c, pc.br
@@ -112,7 +112,7 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
} }
if err := writeFramePrefixed(conn, pc.wbuf); err != nil { if err := writeFramePrefixed(conn, pc.wbuf); err != nil {
conn.Close() conn.Close()
return fmt.Errorf("zap: write request: %w", err) return fmt.Errorf("zaphttp: write request: %w", err)
} }
if t.readTimeout > 0 { if t.readTimeout > 0 {
@@ -121,13 +121,13 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
pc.rbuf, err = readFrameInto(br, pc.rbuf) pc.rbuf, err = readFrameInto(br, pc.rbuf)
if err != nil { if err != nil {
conn.Close() conn.Close()
return fmt.Errorf("zap: read response: %w", err) return fmt.Errorf("zaphttp: read response: %w", err)
} }
respFrame := pc.rbuf respFrame := pc.rbuf
ft, ok := frameType(respFrame) ft, ok := frameType(respFrame)
if !ok { if !ok {
conn.Close() conn.Close()
return fmt.Errorf("zap: short response frame") return fmt.Errorf("zaphttp: short response frame")
} }
// Streamed response: apply the head, then attach a body stream that reads // Streamed response: apply the head, then attach a body stream that reads
@@ -138,7 +138,7 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
if ft == FrameResponseHead { if ft == FrameResponseHead {
if err := UnmarshalResponseHead(respFrame, resp); err != nil { if err := UnmarshalResponseHead(respFrame, resp); err != nil {
conn.Close() conn.Close()
return fmt.Errorf("zap: unmarshal response head: %w", err) return fmt.Errorf("zaphttp: unmarshal response head: %w", err)
} }
resp.SetBodyStream(&streamReader{t: t, pc: pc, br: br}, -1) resp.SetBodyStream(&streamReader{t: t, pc: pc, br: br}, -1)
return nil return nil
@@ -146,7 +146,7 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
if err := UnmarshalResponse(respFrame, resp); err != nil { if err := UnmarshalResponse(respFrame, resp); err != nil {
conn.Close() conn.Close()
return fmt.Errorf("zap: unmarshal response: %w", err) return fmt.Errorf("zaphttp: unmarshal response: %w", err)
} }
// Reset the read deadline and return the conn to the pool. The response // Reset the read deadline and return the conn to the pool. The response
@@ -209,7 +209,7 @@ func (s *streamReader) Read(p []byte) (int, error) {
s.release() s.release()
return 0, io.EOF return 0, io.EOF
default: default:
s.err = fmt.Errorf("zap: unexpected frame %#x mid-stream", ft) s.err = fmt.Errorf("zaphttp: unexpected frame %#x mid-stream", ft)
return 0, s.err return 0, s.err
} }
} }
+5 -5
View File
@@ -25,7 +25,7 @@
// relOffset is patched to point at them. An empty text/bytes field stays a // relOffset is patched to point at them. An empty text/bytes field stays a
// zeroed {0,0} slot with no tail entry. This is exactly what zap.Builder emits. // zeroed {0,0} slot with no tail entry. This is exactly what zap.Builder emits.
package zap package http
import ( import (
"encoding/binary" "encoding/binary"
@@ -123,7 +123,7 @@ func AppendRequest(dst []byte, req *fasthttp.Request) ([]byte, error) {
trailer, err := encodeTrailers(&req.Header) trailer, err := encodeTrailers(&req.Header)
if err != nil { if err != nil {
return dst, fmt.Errorf("zap: encode trailer: %w", err) return dst, fmt.Errorf("zaphttp: encode trailer: %w", err)
} }
dst = putVarBytes(dst, obj+reqTrailer, trailer) dst = putVarBytes(dst, obj+reqTrailer, trailer)
@@ -167,7 +167,7 @@ func AppendResponse(dst []byte, resp *fasthttp.Response) ([]byte, error) {
trailer, err := encodeTrailers(&resp.Header) trailer, err := encodeTrailers(&resp.Header)
if err != nil { if err != nil {
return dst, fmt.Errorf("zap: encode trailer: %w", err) return dst, fmt.Errorf("zaphttp: encode trailer: %w", err)
} }
dst = putVarBytes(dst, obj+respTrailer, trailer) dst = putVarBytes(dst, obj+respTrailer, trailer)
@@ -198,7 +198,7 @@ func frameRoot(frame []byte, wantType uint16) (root, size int, err error) {
return 0, 0, zap.ErrBufferTooSmall return 0, 0, zap.ErrBufferTooSmall
} }
if t := binary.LittleEndian.Uint16(frame[6:8]) >> 8; t != wantType { if t := binary.LittleEndian.Uint16(frame[6:8]) >> 8; t != wantType {
return 0, 0, fmt.Errorf("zap: frame type %#x, want %#x", t, wantType) return 0, 0, fmt.Errorf("zaphttp: frame type %#x, want %#x", t, wantType)
} }
root = int(binary.LittleEndian.Uint32(frame[8:12])) root = int(binary.LittleEndian.Uint32(frame[8:12]))
if root < zap.HeaderSize || root >= size { if root < zap.HeaderSize || root >= size {
@@ -347,7 +347,7 @@ func emitHeaders(dst []byte, pairs []hpair) []byte {
} }
// errHeaderShort reports a header block that ends mid-field. // errHeaderShort reports a header block that ends mid-field.
var errHeaderShort = errors.New("zap: truncated header block") var errHeaderShort = errors.New("zaphttp: truncated header block")
// forEachHeader calls fn for every pair in raw. Keys and values alias raw and // forEachHeader calls fn for every pair in raw. Keys and values alias raw and
// must not outlive it. // must not outlive it.
+1 -1
View File
@@ -1,4 +1,4 @@
package zap package http
import ( import (
"strings" "strings"
+1 -1
View File
@@ -1,4 +1,4 @@
package zap package http
import ( import (
"testing" "testing"
+22 -22
View File
@@ -6,7 +6,7 @@
// accidental format change fails loudly. They were regenerated once, // accidental format change fails loudly. They were regenerated once,
// deliberately, when headers moved from a JSON map to length-prefixed pairs. // deliberately, when headers moved from a JSON map to length-prefixed pairs.
package zap_test package http_test
import ( import (
"bytes" "bytes"
@@ -42,7 +42,7 @@ func listen(t *testing.T, handler fasthttp.RequestHandler) (addr string, shutdow
if err != nil { if err != nil {
t.Fatalf("listen: %v", err) t.Fatalf("listen: %v", err)
} }
srv := &zap.Server{Handler: handler} srv := &http.Server{Handler: handler}
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(1) wg.Add(1)
go func() { go func() {
@@ -61,7 +61,7 @@ func listen(t *testing.T, handler fasthttp.RequestHandler) (addr string, shutdow
// response the caller must release. // response the caller must release.
func do(t *testing.T, addr, method, path string, body []byte, mutate func(*fasthttp.Request)) *fasthttp.Response { func do(t *testing.T, addr, method, path string, body []byte, mutate func(*fasthttp.Request)) *fasthttp.Response {
t.Helper() t.Helper()
tr := zap.Dial("tcp", addr) tr := http.Dial("tcp", addr)
req := fasthttp.AcquireRequest() req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req) defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod(method) req.Header.SetMethod(method)
@@ -241,7 +241,7 @@ func TestKeepAlive(t *testing.T) {
}) })
defer stop() defer stop()
tr := zap.Dial("tcp", addr) tr := http.Dial("tcp", addr)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
path := fmt.Sprintf("/req-%d", i) path := fmt.Sprintf("/req-%d", i)
req := fasthttp.AcquireRequest() req := fasthttp.AcquireRequest()
@@ -271,12 +271,12 @@ func TestMarshalRequest_idempotent(t *testing.T) {
orig.Header.Set("Authorization", "Bearer token-stays-encrypted-on-the-wire") orig.Header.Set("Authorization", "Bearer token-stays-encrypted-on-the-wire")
orig.SetBody(body) orig.SetBody(body)
frame, err := zap.MarshalRequest(orig) frame, err := http.MarshalRequest(orig)
if err != nil { if err != nil {
t.Fatalf("marshal: %v", err) t.Fatalf("marshal: %v", err)
} }
var got fasthttp.Request var got fasthttp.Request
if err := zap.UnmarshalRequest(frame, &got); err != nil { if err := http.UnmarshalRequest(frame, &got); err != nil {
t.Fatalf("unmarshal: %v", err) t.Fatalf("unmarshal: %v", err)
} }
if string(got.Header.Method()) != fasthttp.MethodPost { if string(got.Header.Method()) != fasthttp.MethodPost {
@@ -314,12 +314,12 @@ func TestMarshalResponse_idempotent(t *testing.T) {
} }
orig.Header.Set("X-Checksum", "deadbeef") orig.Header.Set("X-Checksum", "deadbeef")
frame, err := zap.MarshalResponse(orig) frame, err := http.MarshalResponse(orig)
if err != nil { if err != nil {
t.Fatalf("marshal: %v", err) t.Fatalf("marshal: %v", err)
} }
var got fasthttp.Response var got fasthttp.Response
if err := zap.UnmarshalResponse(frame, &got); err != nil { if err := http.UnmarshalResponse(frame, &got); err != nil {
t.Fatalf("unmarshal: %v", err) t.Fatalf("unmarshal: %v", err)
} }
if got.StatusCode() != fasthttp.StatusTeapot { if got.StatusCode() != fasthttp.StatusTeapot {
@@ -345,24 +345,24 @@ func TestFrameType_crossGuard(t *testing.T) {
defer fasthttp.ReleaseRequest(req) defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod(fasthttp.MethodGet) req.Header.SetMethod(fasthttp.MethodGet)
req.SetRequestURI("/x") req.SetRequestURI("/x")
reqFrame, err := zap.MarshalRequest(req) reqFrame, err := http.MarshalRequest(req)
if err != nil { if err != nil {
t.Fatalf("marshal request: %v", err) t.Fatalf("marshal request: %v", err)
} }
var asResp fasthttp.Response var asResp fasthttp.Response
if err := zap.UnmarshalResponse(reqFrame, &asResp); err == nil { if err := http.UnmarshalResponse(reqFrame, &asResp); err == nil {
t.Errorf("UnmarshalResponse accepted a request frame; want error") t.Errorf("UnmarshalResponse accepted a request frame; want error")
} }
resp := fasthttp.AcquireResponse() resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp) defer fasthttp.ReleaseResponse(resp)
resp.SetStatusCode(fasthttp.StatusOK) resp.SetStatusCode(fasthttp.StatusOK)
respFrame, err := zap.MarshalResponse(resp) respFrame, err := http.MarshalResponse(resp)
if err != nil { if err != nil {
t.Fatalf("marshal response: %v", err) t.Fatalf("marshal response: %v", err)
} }
var asReq fasthttp.Request var asReq fasthttp.Request
if err := zap.UnmarshalRequest(respFrame, &asReq); err == nil { if err := http.UnmarshalRequest(respFrame, &asReq); err == nil {
t.Errorf("UnmarshalRequest accepted a response frame; want error") t.Errorf("UnmarshalRequest accepted a response frame; want error")
} }
} }
@@ -372,12 +372,12 @@ func TestEmptyHeaders_decode(t *testing.T) {
defer fasthttp.ReleaseRequest(req) defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod(fasthttp.MethodGet) req.Header.SetMethod(fasthttp.MethodGet)
req.SetRequestURI("/") req.SetRequestURI("/")
frame, err := zap.MarshalRequest(req) frame, err := http.MarshalRequest(req)
if err != nil { if err != nil {
t.Fatalf("marshal: %v", err) t.Fatalf("marshal: %v", err)
} }
var got fasthttp.Request var got fasthttp.Request
if err := zap.UnmarshalRequest(frame, &got); err != nil { if err := http.UnmarshalRequest(frame, &got); err != nil {
t.Fatalf("unmarshal: %v", err) t.Fatalf("unmarshal: %v", err)
} }
got.Header.Add("X-Added", "ok") // must not panic got.Header.Add("X-Added", "ok") // must not panic
@@ -401,7 +401,7 @@ func mustHex(t *testing.T, s string) []byte {
// produced by the prior net/http codec faithfully (backward wire compat). // produced by the prior net/http codec faithfully (backward wire compat).
func TestWireGolden_DecodeRequest(t *testing.T) { func TestWireGolden_DecodeRequest(t *testing.T) {
var req fasthttp.Request var req fasthttp.Request
if err := zap.UnmarshalRequest(mustHex(t, goldenRequest), &req); err != nil { if err := http.UnmarshalRequest(mustHex(t, goldenRequest), &req); err != nil {
t.Fatalf("decode golden request: %v", err) t.Fatalf("decode golden request: %v", err)
} }
if string(req.Header.Method()) != "POST" { if string(req.Header.Method()) != "POST" {
@@ -423,7 +423,7 @@ func TestWireGolden_DecodeRequest(t *testing.T) {
func TestWireGolden_DecodeResponse(t *testing.T) { func TestWireGolden_DecodeResponse(t *testing.T) {
var resp fasthttp.Response var resp fasthttp.Response
if err := zap.UnmarshalResponse(mustHex(t, goldenResponse), &resp); err != nil { if err := http.UnmarshalResponse(mustHex(t, goldenResponse), &resp); err != nil {
t.Fatalf("decode golden response: %v", err) t.Fatalf("decode golden response: %v", err)
} }
if resp.StatusCode() != 200 { if resp.StatusCode() != 200 {
@@ -452,7 +452,7 @@ func TestWireGolden_EncodeRequest(t *testing.T) {
req.Header.Set("X-Trace-Id", "abc-123") req.Header.Set("X-Trace-Id", "abc-123")
req.SetBody([]byte(`{"jsonrpc":"2.0","method":"eth_blockNumber"}`)) req.SetBody([]byte(`{"jsonrpc":"2.0","method":"eth_blockNumber"}`))
frame, err := zap.MarshalRequest(req) frame, err := http.MarshalRequest(req)
if err != nil { if err != nil {
t.Fatalf("marshal: %v", err) t.Fatalf("marshal: %v", err)
} }
@@ -470,7 +470,7 @@ func TestWireGolden_EncodeResponse(t *testing.T) {
resp.Header.Set("X-Trace-Id", "abc-123") resp.Header.Set("X-Trace-Id", "abc-123")
resp.SetBody([]byte(`{"result":"0x2a"}`)) resp.SetBody([]byte(`{"result":"0x2a"}`))
frame, err := zap.MarshalResponse(resp) frame, err := http.MarshalResponse(resp)
if err != nil { if err != nil {
t.Fatalf("marshal: %v", err) t.Fatalf("marshal: %v", err)
} }
@@ -486,7 +486,7 @@ func TestWireGolden_EncodeEmptyRequest(t *testing.T) {
req.SetRequestURI("/health") req.SetRequestURI("/health")
req.Header.SetProtocol("HTTP/1.1") req.Header.SetProtocol("HTTP/1.1")
frame, err := zap.MarshalRequest(req) frame, err := http.MarshalRequest(req)
if err != nil { if err != nil {
t.Fatalf("marshal: %v", err) t.Fatalf("marshal: %v", err)
} }
@@ -500,7 +500,7 @@ func TestWireGolden_EncodeEmptyRequest(t *testing.T) {
// codec's output. // codec's output.
func TestWireGolden_TrailerResponse(t *testing.T) { func TestWireGolden_TrailerResponse(t *testing.T) {
var resp fasthttp.Response var resp fasthttp.Response
if err := zap.UnmarshalResponse(mustHex(t, goldenTrailerResponse), &resp); err != nil { if err := http.UnmarshalResponse(mustHex(t, goldenTrailerResponse), &resp); err != nil {
t.Fatalf("decode golden trailer response: %v", err) t.Fatalf("decode golden trailer response: %v", err)
} }
if string(resp.Header.ContentType()) != "application/octet-stream" { if string(resp.Header.ContentType()) != "application/octet-stream" {
@@ -512,7 +512,7 @@ func TestWireGolden_TrailerResponse(t *testing.T) {
if cs := string(resp.Header.Peek("X-Checksum")); cs != "deadbeef" { if cs := string(resp.Header.Peek("X-Checksum")); cs != "deadbeef" {
t.Errorf("trailer X-Checksum = %q want deadbeef", cs) t.Errorf("trailer X-Checksum = %q want deadbeef", cs)
} }
frame, err := zap.MarshalResponse(&resp) frame, err := http.MarshalResponse(&resp)
if err != nil { if err != nil {
t.Fatalf("re-marshal: %v", err) t.Fatalf("re-marshal: %v", err)
} }
@@ -529,7 +529,7 @@ func TestConnReuse(t *testing.T) {
defer stop() defer stop()
_ = dials _ = dials
tr := zap.Dial("tcp", addr) tr := http.Dial("tcp", addr)
deadline := time.Now().Add(2 * time.Second) deadline := time.Now().Add(2 * time.Second)
for i := 0; i < 3 && time.Now().Before(deadline); i++ { for i := 0; i < 3 && time.Now().Before(deadline); i++ {
resp := fasthttp.AcquireResponse() resp := fasthttp.AcquireResponse()
+9 -9
View File
@@ -2,7 +2,7 @@
// //
// A Fiber app (or any fasthttp stack) hands its handler straight in: // A Fiber app (or any fasthttp stack) hands its handler straight in:
// //
// srv := &zap.Server{Addr: ":9999", Handler: app.Handler()} // srv := &http.Server{Addr: ":9999", Handler: app.Handler()}
// srv.ListenAndServe() // srv.ListenAndServe()
// //
// The server reads ZAP-HTTP frames off each accepted connection, // The server reads ZAP-HTTP frames off each accepted connection,
@@ -10,7 +10,7 @@
// writes one response frame back from the ctx's Response. Connections are // writes one response frame back from the ctx's Response. Connections are
// kept alive across requests. There is no net/http anywhere in the path. // kept alive across requests. There is no net/http anywhere in the path.
package zap package http
import ( import (
"bufio" "bufio"
@@ -69,7 +69,7 @@ func (s *Server) ListenAndServe() error {
// fails, because something is genuinely listening. // fails, because something is genuinely listening.
if c, err := net.DialTimeout("unix", addr, 200*time.Millisecond); err == nil { if c, err := net.DialTimeout("unix", addr, 200*time.Millisecond); err == nil {
_ = c.Close() _ = c.Close()
return fmt.Errorf("zap: %s is already served by a live process", addr) return fmt.Errorf("zaphttp: %s is already served by a live process", addr)
} }
_ = os.Remove(addr) _ = os.Remove(addr)
} }
@@ -88,7 +88,7 @@ func (s *Server) Serve(ln net.Listener) error {
s.mu.Unlock() s.mu.Unlock()
if s.Handler == nil { if s.Handler == nil {
return errors.New("zap: Server.Handler is nil") return errors.New("zaphttp: Server.Handler is nil")
} }
for { for {
@@ -136,7 +136,7 @@ func (s *Server) serveConn(conn net.Conn) {
readBuf, err = readFrameInto(br, readBuf) readBuf, err = readFrameInto(br, readBuf)
if err != nil { if err != nil {
if !errors.Is(err, io.EOF) && !isClosedConn(err) { if !errors.Is(err, io.EOF) && !isClosedConn(err) {
log.Printf("zap: read frame: %v", err) log.Printf("zaphttp: read frame: %v", err)
} }
return return
} }
@@ -161,7 +161,7 @@ func (s *Server) serveConn(conn net.Conn) {
if r := recover(); r != nil { if r := recover(); r != nil {
ctx.Response.Reset() ctx.Response.Reset()
ctx.Response.SetStatusCode(fasthttp.StatusInternalServerError) ctx.Response.SetStatusCode(fasthttp.StatusInternalServerError)
log.Printf("zap: handler panic on %s %s: %v", log.Printf("zaphttp: handler panic on %s %s: %v",
ctx.Method(), ctx.RequestURI(), r) ctx.Method(), ctx.RequestURI(), r)
} }
}() }()
@@ -179,7 +179,7 @@ func (s *Server) serveConn(conn net.Conn) {
if ctx.Response.IsBodyStream() { if ctx.Response.IsBodyStream() {
if err := s.streamResponse(conn, &ctx.Response); err != nil { if err := s.streamResponse(conn, &ctx.Response); err != nil {
if !isClosedConn(err) { if !isClosedConn(err) {
log.Printf("zap: stream response: %v", err) log.Printf("zaphttp: stream response: %v", err)
} }
return return
} }
@@ -191,12 +191,12 @@ func (s *Server) serveConn(conn net.Conn) {
writeBuf = append(writeBuf[:0], 0, 0, 0, 0) writeBuf = append(writeBuf[:0], 0, 0, 0, 0)
writeBuf, err = AppendResponse(writeBuf, &ctx.Response) writeBuf, err = AppendResponse(writeBuf, &ctx.Response)
if err != nil { if err != nil {
log.Printf("zap: marshal response: %v", err) log.Printf("zaphttp: marshal response: %v", err)
return return
} }
if err := writeFramePrefixed(conn, writeBuf); err != nil { if err := writeFramePrefixed(conn, writeBuf); err != nil {
if !isClosedConn(err) { if !isClosedConn(err) {
log.Printf("zap: write frame: %v", err) log.Printf("zaphttp: write frame: %v", err)
} }
return return
} }
+2 -2
View File
@@ -1,4 +1,4 @@
package zap_test package http_test
import ( import (
"bufio" "bufio"
@@ -34,7 +34,7 @@ func TestStream_SSEOverZAP(t *testing.T) {
}) })
defer stop() defer stop()
tr := zap.Dial("tcp", addr) tr := http.Dial("tcp", addr)
defer tr.CloseIdleConnections() defer tr.CloseIdleConnections()
req := fasthttp.AcquireRequest() req := fasthttp.AcquireRequest()
resp := fasthttp.AcquireResponse() resp := fasthttp.AcquireResponse()
+8 -8
View File
@@ -11,7 +11,7 @@
// across exchanges (HTTP/1.1-style keep-alive); the transport itself // across exchanges (HTTP/1.1-style keep-alive); the transport itself
// does not pipeline. // does not pipeline.
package zap package http
import ( import (
"bufio" "bufio"
@@ -52,10 +52,10 @@ func readFrameInto(r *bufio.Reader, buf []byte) ([]byte, error) {
return buf, err return buf, err
} }
if n == 0 { if n == 0 {
return buf, fmt.Errorf("zap: zero-length frame") return buf, fmt.Errorf("zaphttp: zero-length frame")
} }
if n > MaxFrameSize { if n > MaxFrameSize {
return buf, fmt.Errorf("zap: frame size %d exceeds MaxFrameSize=%d", n, MaxFrameSize) return buf, fmt.Errorf("zaphttp: frame size %d exceeds MaxFrameSize=%d", n, MaxFrameSize)
} }
if uint32(cap(buf)) < n { if uint32(cap(buf)) < n {
buf = make([]byte, n) buf = make([]byte, n)
@@ -65,7 +65,7 @@ func readFrameInto(r *bufio.Reader, buf []byte) ([]byte, error) {
// buf is already heap-backed (persistent across calls), so ReadFull's // buf is already heap-backed (persistent across calls), so ReadFull's
// interface indirection costs no new allocation here. // interface indirection costs no new allocation here.
if _, err := io.ReadFull(r, buf); err != nil { if _, err := io.ReadFull(r, buf); err != nil {
return buf, fmt.Errorf("zap: short frame: %w", err) return buf, fmt.Errorf("zaphttp: short frame: %w", err)
} }
return buf, nil return buf, nil
} }
@@ -77,10 +77,10 @@ func readFrameInto(r *bufio.Reader, buf []byte) ([]byte, error) {
func writeFramePrefixed(w io.Writer, framePlusPrefix []byte) error { func writeFramePrefixed(w io.Writer, framePlusPrefix []byte) error {
body := len(framePlusPrefix) - 4 body := len(framePlusPrefix) - 4
if body <= 0 { if body <= 0 {
return fmt.Errorf("zap: refusing to write zero-length frame") return fmt.Errorf("zaphttp: refusing to write zero-length frame")
} }
if uint64(body) > MaxFrameSize { if uint64(body) > MaxFrameSize {
return fmt.Errorf("zap: frame size %d exceeds MaxFrameSize=%d", body, MaxFrameSize) return fmt.Errorf("zaphttp: frame size %d exceeds MaxFrameSize=%d", body, MaxFrameSize)
} }
binary.BigEndian.PutUint32(framePlusPrefix[0:4], uint32(body)) binary.BigEndian.PutUint32(framePlusPrefix[0:4], uint32(body))
_, err := w.Write(framePlusPrefix) _, err := w.Write(framePlusPrefix)
@@ -90,10 +90,10 @@ func writeFramePrefixed(w io.Writer, framePlusPrefix []byte) error {
// writeFrame writes one length-prefixed frame to w. // writeFrame writes one length-prefixed frame to w.
func writeFrame(w io.Writer, frame []byte) error { func writeFrame(w io.Writer, frame []byte) error {
if len(frame) == 0 { if len(frame) == 0 {
return fmt.Errorf("zap: refusing to write zero-length frame") return fmt.Errorf("zaphttp: refusing to write zero-length frame")
} }
if uint64(len(frame)) > MaxFrameSize { if uint64(len(frame)) > MaxFrameSize {
return fmt.Errorf("zap: frame size %d exceeds MaxFrameSize=%d", len(frame), MaxFrameSize) return fmt.Errorf("zaphttp: frame size %d exceeds MaxFrameSize=%d", len(frame), MaxFrameSize)
} }
var hdr [4]byte var hdr [4]byte
binary.BigEndian.PutUint32(hdr[:], uint32(len(frame))) binary.BigEndian.PutUint32(hdr[:], uint32(len(frame)))
+6 -6
View File
@@ -1,4 +1,4 @@
// Package zap implements HTTP request/response semantics over the // Package zaphttp implements HTTP request/response semantics over the
// ZAP transport for the fasthttp handler model. A fasthttp.RequestHandler // ZAP transport for the fasthttp handler model. A fasthttp.RequestHandler
// is served over ZAP frames; a fasthttp.Request/Response pair is exchanged // is served over ZAP frames; a fasthttp.Request/Response pair is exchanged
// by the client. There is no net/http in the request path — Fiber and // by the client. There is no net/http in the request path — Fiber and
@@ -49,7 +49,7 @@
// repeated pair, which covers multi-value headers (RFC 9110 §5.2) without // repeated pair, which covers multi-value headers (RFC 9110 §5.2) without
// modelling a list. // modelling a list.
package zap package http
import ( import (
"encoding/binary" "encoding/binary"
@@ -166,10 +166,10 @@ func UnmarshalRequest(frame []byte, dst *fasthttp.Request) error {
dst.Header.SetProtocolBytes(proto) dst.Header.SetProtocolBytes(proto)
} }
if err := decodeRequestHeaders(&dst.Header, headers); err != nil { if err := decodeRequestHeaders(&dst.Header, headers); err != nil {
return fmt.Errorf("zap: decode headers: %w", err) return fmt.Errorf("zaphttp: decode headers: %w", err)
} }
if err := applyTrailers(&dst.Header, trailer); err != nil { if err := applyTrailers(&dst.Header, trailer); err != nil {
return fmt.Errorf("zap: decode trailer: %w", err) return fmt.Errorf("zaphttp: decode trailer: %w", err)
} }
dst.SetBody(body) dst.SetBody(body)
return nil return nil
@@ -197,10 +197,10 @@ func UnmarshalResponse(frame []byte, dst *fasthttp.Response) error {
dst.Header.SetProtocol(proto) dst.Header.SetProtocol(proto)
} }
if err := decodeResponseHeaders(&dst.Header, headers); err != nil { if err := decodeResponseHeaders(&dst.Header, headers); err != nil {
return fmt.Errorf("zap: decode headers: %w", err) return fmt.Errorf("zaphttp: decode headers: %w", err)
} }
if err := applyTrailers(&dst.Header, trailer); err != nil { if err := applyTrailers(&dst.Header, trailer); err != nil {
return fmt.Errorf("zap: decode trailer: %w", err) return fmt.Errorf("zaphttp: decode trailer: %w", err)
} }
dst.SetBody(body) dst.SetBody(body)
return nil return nil