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 /
// MarshalResponse / UnmarshalRequest / UnmarshalResponse, so the SAME file
@@ -34,7 +34,7 @@ func BenchmarkCompat_MarshalRequest(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := zap.MarshalRequest(req); err != nil {
if _, err := http.MarshalRequest(req); err != nil {
b.Fatal(err)
}
}
@@ -46,7 +46,7 @@ func BenchmarkCompat_MarshalResponse(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := zap.MarshalResponse(resp); err != nil {
if _, err := http.MarshalResponse(resp); err != nil {
b.Fatal(err)
}
}
@@ -54,13 +54,13 @@ func BenchmarkCompat_MarshalResponse(b *testing.B) {
func BenchmarkCompat_UnmarshalRequest(b *testing.B) {
req := compatReq()
frame, _ := zap.MarshalRequest(req)
frame, _ := http.MarshalRequest(req)
fasthttp.ReleaseRequest(req)
var dst fasthttp.Request
b.ReportAllocs()
b.ResetTimer()
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)
}
}
@@ -68,13 +68,13 @@ func BenchmarkCompat_UnmarshalRequest(b *testing.B) {
func BenchmarkCompat_UnmarshalResponse(b *testing.B) {
resp := compatResp()
frame, _ := zap.MarshalResponse(resp)
frame, _ := http.MarshalResponse(resp)
fasthttp.ReleaseResponse(resp)
var dst fasthttp.Response
b.ReportAllocs()
b.ResetTimer()
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)
}
}
+12 -12
View File
@@ -2,7 +2,7 @@
//
// Usage mirrors fasthttp's Do(req, resp):
//
// t := zap.Dial("tcp", "server:9999")
// t := http.Dial("tcp", "server:9999")
// req := fasthttp.AcquireRequest()
// resp := fasthttp.AcquireResponse()
// req.SetRequestURI("/healthz")
@@ -16,7 +16,7 @@
// decoded — no body-close handshake is needed. The pool caps at
// MaxIdleConns; surplus conns close on return.
package zap
package http
import (
"bufio"
@@ -57,8 +57,8 @@ type Transport struct {
// functions. A unix address is a socket path and carries the same ZAP frames
// as tcp — the wire does not change with the network.
//
// zap.Dial("tcp", "billing.hanzo.svc:9653")
// zap.Dial("unix", "/run/hanzo/billing.sock")
// http.Dial("tcp", "billing.hanzo.svc:9653")
// http.Dial("unix", "/run/hanzo/billing.sock")
//
// Dialing is lazy; the first request opens the connection.
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.
func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
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()
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
@@ -112,7 +112,7 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
}
if err := writeFramePrefixed(conn, pc.wbuf); err != nil {
conn.Close()
return fmt.Errorf("zap: write request: %w", err)
return fmt.Errorf("zaphttp: write request: %w", err)
}
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)
if err != nil {
conn.Close()
return fmt.Errorf("zap: read response: %w", err)
return fmt.Errorf("zaphttp: read response: %w", err)
}
respFrame := pc.rbuf
ft, ok := frameType(respFrame)
if !ok {
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
@@ -138,7 +138,7 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
if ft == FrameResponseHead {
if err := UnmarshalResponseHead(respFrame, resp); err != nil {
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)
return nil
@@ -146,7 +146,7 @@ func (t *Transport) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
if err := UnmarshalResponse(respFrame, resp); err != nil {
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
@@ -209,7 +209,7 @@ func (s *streamReader) Read(p []byte) (int, error) {
s.release()
return 0, io.EOF
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
}
}
+5 -5
View File
@@ -25,7 +25,7 @@
// 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.
package zap
package http
import (
"encoding/binary"
@@ -123,7 +123,7 @@ func AppendRequest(dst []byte, req *fasthttp.Request) ([]byte, error) {
trailer, err := encodeTrailers(&req.Header)
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)
@@ -167,7 +167,7 @@ func AppendResponse(dst []byte, resp *fasthttp.Response) ([]byte, error) {
trailer, err := encodeTrailers(&resp.Header)
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)
@@ -198,7 +198,7 @@ func frameRoot(frame []byte, wantType uint16) (root, size int, err error) {
return 0, 0, zap.ErrBufferTooSmall
}
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]))
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.
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
// must not outlive it.
+1 -1
View File
@@ -1,4 +1,4 @@
package zap
package http
import (
"strings"
+1 -1
View File
@@ -1,4 +1,4 @@
package zap
package http
import (
"testing"
+22 -22
View File
@@ -6,7 +6,7 @@
// accidental format change fails loudly. They were regenerated once,
// deliberately, when headers moved from a JSON map to length-prefixed pairs.
package zap_test
package http_test
import (
"bytes"
@@ -42,7 +42,7 @@ func listen(t *testing.T, handler fasthttp.RequestHandler) (addr string, shutdow
if err != nil {
t.Fatalf("listen: %v", err)
}
srv := &zap.Server{Handler: handler}
srv := &http.Server{Handler: handler}
var wg sync.WaitGroup
wg.Add(1)
go func() {
@@ -61,7 +61,7 @@ func listen(t *testing.T, handler fasthttp.RequestHandler) (addr string, shutdow
// response the caller must release.
func do(t *testing.T, addr, method, path string, body []byte, mutate func(*fasthttp.Request)) *fasthttp.Response {
t.Helper()
tr := zap.Dial("tcp", addr)
tr := http.Dial("tcp", addr)
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod(method)
@@ -241,7 +241,7 @@ func TestKeepAlive(t *testing.T) {
})
defer stop()
tr := zap.Dial("tcp", addr)
tr := http.Dial("tcp", addr)
for i := 0; i < 5; i++ {
path := fmt.Sprintf("/req-%d", i)
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.SetBody(body)
frame, err := zap.MarshalRequest(orig)
frame, err := http.MarshalRequest(orig)
if err != nil {
t.Fatalf("marshal: %v", err)
}
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)
}
if string(got.Header.Method()) != fasthttp.MethodPost {
@@ -314,12 +314,12 @@ func TestMarshalResponse_idempotent(t *testing.T) {
}
orig.Header.Set("X-Checksum", "deadbeef")
frame, err := zap.MarshalResponse(orig)
frame, err := http.MarshalResponse(orig)
if err != nil {
t.Fatalf("marshal: %v", err)
}
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)
}
if got.StatusCode() != fasthttp.StatusTeapot {
@@ -345,24 +345,24 @@ func TestFrameType_crossGuard(t *testing.T) {
defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod(fasthttp.MethodGet)
req.SetRequestURI("/x")
reqFrame, err := zap.MarshalRequest(req)
reqFrame, err := http.MarshalRequest(req)
if err != nil {
t.Fatalf("marshal request: %v", err)
}
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")
}
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp)
resp.SetStatusCode(fasthttp.StatusOK)
respFrame, err := zap.MarshalResponse(resp)
respFrame, err := http.MarshalResponse(resp)
if err != nil {
t.Fatalf("marshal response: %v", err)
}
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")
}
}
@@ -372,12 +372,12 @@ func TestEmptyHeaders_decode(t *testing.T) {
defer fasthttp.ReleaseRequest(req)
req.Header.SetMethod(fasthttp.MethodGet)
req.SetRequestURI("/")
frame, err := zap.MarshalRequest(req)
frame, err := http.MarshalRequest(req)
if err != nil {
t.Fatalf("marshal: %v", err)
}
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)
}
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).
func TestWireGolden_DecodeRequest(t *testing.T) {
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)
}
if string(req.Header.Method()) != "POST" {
@@ -423,7 +423,7 @@ func TestWireGolden_DecodeRequest(t *testing.T) {
func TestWireGolden_DecodeResponse(t *testing.T) {
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)
}
if resp.StatusCode() != 200 {
@@ -452,7 +452,7 @@ func TestWireGolden_EncodeRequest(t *testing.T) {
req.Header.Set("X-Trace-Id", "abc-123")
req.SetBody([]byte(`{"jsonrpc":"2.0","method":"eth_blockNumber"}`))
frame, err := zap.MarshalRequest(req)
frame, err := http.MarshalRequest(req)
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -470,7 +470,7 @@ func TestWireGolden_EncodeResponse(t *testing.T) {
resp.Header.Set("X-Trace-Id", "abc-123")
resp.SetBody([]byte(`{"result":"0x2a"}`))
frame, err := zap.MarshalResponse(resp)
frame, err := http.MarshalResponse(resp)
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -486,7 +486,7 @@ func TestWireGolden_EncodeEmptyRequest(t *testing.T) {
req.SetRequestURI("/health")
req.Header.SetProtocol("HTTP/1.1")
frame, err := zap.MarshalRequest(req)
frame, err := http.MarshalRequest(req)
if err != nil {
t.Fatalf("marshal: %v", err)
}
@@ -500,7 +500,7 @@ func TestWireGolden_EncodeEmptyRequest(t *testing.T) {
// codec's output.
func TestWireGolden_TrailerResponse(t *testing.T) {
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)
}
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" {
t.Errorf("trailer X-Checksum = %q want deadbeef", cs)
}
frame, err := zap.MarshalResponse(&resp)
frame, err := http.MarshalResponse(&resp)
if err != nil {
t.Fatalf("re-marshal: %v", err)
}
@@ -529,7 +529,7 @@ func TestConnReuse(t *testing.T) {
defer stop()
_ = dials
tr := zap.Dial("tcp", addr)
tr := http.Dial("tcp", addr)
deadline := time.Now().Add(2 * time.Second)
for i := 0; i < 3 && time.Now().Before(deadline); i++ {
resp := fasthttp.AcquireResponse()
+9 -9
View File
@@ -2,7 +2,7 @@
//
// 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()
//
// 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
// kept alive across requests. There is no net/http anywhere in the path.
package zap
package http
import (
"bufio"
@@ -69,7 +69,7 @@ func (s *Server) ListenAndServe() error {
// fails, because something is genuinely listening.
if c, err := net.DialTimeout("unix", addr, 200*time.Millisecond); err == nil {
_ = 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)
}
@@ -88,7 +88,7 @@ func (s *Server) Serve(ln net.Listener) error {
s.mu.Unlock()
if s.Handler == nil {
return errors.New("zap: Server.Handler is nil")
return errors.New("zaphttp: Server.Handler is nil")
}
for {
@@ -136,7 +136,7 @@ func (s *Server) serveConn(conn net.Conn) {
readBuf, err = readFrameInto(br, readBuf)
if err != nil {
if !errors.Is(err, io.EOF) && !isClosedConn(err) {
log.Printf("zap: read frame: %v", err)
log.Printf("zaphttp: read frame: %v", err)
}
return
}
@@ -161,7 +161,7 @@ func (s *Server) serveConn(conn net.Conn) {
if r := recover(); r != nil {
ctx.Response.Reset()
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)
}
}()
@@ -179,7 +179,7 @@ func (s *Server) serveConn(conn net.Conn) {
if ctx.Response.IsBodyStream() {
if err := s.streamResponse(conn, &ctx.Response); err != nil {
if !isClosedConn(err) {
log.Printf("zap: stream response: %v", err)
log.Printf("zaphttp: stream response: %v", err)
}
return
}
@@ -191,12 +191,12 @@ func (s *Server) serveConn(conn net.Conn) {
writeBuf = append(writeBuf[:0], 0, 0, 0, 0)
writeBuf, err = AppendResponse(writeBuf, &ctx.Response)
if err != nil {
log.Printf("zap: marshal response: %v", err)
log.Printf("zaphttp: marshal response: %v", err)
return
}
if err := writeFramePrefixed(conn, writeBuf); err != nil {
if !isClosedConn(err) {
log.Printf("zap: write frame: %v", err)
log.Printf("zaphttp: write frame: %v", err)
}
return
}
+2 -2
View File
@@ -1,4 +1,4 @@
package zap_test
package http_test
import (
"bufio"
@@ -34,7 +34,7 @@ func TestStream_SSEOverZAP(t *testing.T) {
})
defer stop()
tr := zap.Dial("tcp", addr)
tr := http.Dial("tcp", addr)
defer tr.CloseIdleConnections()
req := fasthttp.AcquireRequest()
resp := fasthttp.AcquireResponse()
+8 -8
View File
@@ -11,7 +11,7 @@
// across exchanges (HTTP/1.1-style keep-alive); the transport itself
// does not pipeline.
package zap
package http
import (
"bufio"
@@ -52,10 +52,10 @@ func readFrameInto(r *bufio.Reader, buf []byte) ([]byte, error) {
return buf, err
}
if n == 0 {
return buf, fmt.Errorf("zap: zero-length frame")
return buf, fmt.Errorf("zaphttp: zero-length frame")
}
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 {
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
// interface indirection costs no new allocation here.
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
}
@@ -77,10 +77,10 @@ func readFrameInto(r *bufio.Reader, buf []byte) ([]byte, error) {
func writeFramePrefixed(w io.Writer, framePlusPrefix []byte) error {
body := len(framePlusPrefix) - 4
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 {
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))
_, err := w.Write(framePlusPrefix)
@@ -90,10 +90,10 @@ func writeFramePrefixed(w io.Writer, framePlusPrefix []byte) error {
// writeFrame writes one length-prefixed frame to w.
func writeFrame(w io.Writer, frame []byte) error {
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 {
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
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
// 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
@@ -49,7 +49,7 @@
// repeated pair, which covers multi-value headers (RFC 9110 §5.2) without
// modelling a list.
package zap
package http
import (
"encoding/binary"
@@ -166,10 +166,10 @@ func UnmarshalRequest(frame []byte, dst *fasthttp.Request) error {
dst.Header.SetProtocolBytes(proto)
}
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 {
return fmt.Errorf("zap: decode trailer: %w", err)
return fmt.Errorf("zaphttp: decode trailer: %w", err)
}
dst.SetBody(body)
return nil
@@ -197,10 +197,10 @@ func UnmarshalResponse(frame []byte, dst *fasthttp.Response) error {
dst.Header.SetProtocol(proto)
}
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 {
return fmt.Errorf("zap: decode trailer: %w", err)
return fmt.Errorf("zaphttp: decode trailer: %w", err)
}
dst.SetBody(body)
return nil