mirror of
https://github.com/zap-proto/zip.git
synced 2026-10-19 15:38:57 +00:00
zip is shared protocol infra (the fiber-over-ZAP web framework used by every
Lux/Hanzo/Zoo Go binary — nodes, gateway, cloud, iam, kms, o11y, ai, …), so its
home is the ZAP protocol family (zap-proto/{go,http,zapd,zip}), NOT any one org's
brand namespace. This consolidates the rich framework (formerly hanzoai/zip v0.5.0
— Ctx/Handler/Errorf/Err*/HTTPError, typed handlers, middleware, runtime/extension
loading, openapi, validate, zaprpc) with the real ZAP transport (ListenZAP/
ListenHTTP/Serve over zap-proto/http) into ONE canonical module.
Module path github.com/hanzoai/zip -> github.com/zap-proto/zip. Code identical to
hanzoai/zip v0.5.0; promoted to v1.0.0 as the stable shared-infra framework. The
prior hanzoai/zip lineage is retired — one home, one import path, one way.
Verified: go build/vet/test ./... green; the ZAP round-trip integration test serves
/v1/health over the real ZAP transport (200 + handler JSON).
73 lines
2.1 KiB
Go
73 lines
2.1 KiB
Go
package zip_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/valyala/fasthttp"
|
|
zaphttp "github.com/zap-proto/http"
|
|
|
|
"github.com/zap-proto/zip"
|
|
)
|
|
|
|
// TestListenZAP_RoundTrip proves the un-stubbed ListenZAP actually SERVES: a
|
|
// route registered on the App answers a real request over the ZAP transport,
|
|
// with the same handler/JSON path as HTTP. (Replaces the old stub that returned
|
|
// "ZAP wire dispatch not yet implemented".)
|
|
func TestListenZAP_RoundTrip(t *testing.T) {
|
|
app := zip.New(zip.Config{AppName: "zaptest", DisableStartupMessage: true})
|
|
app.Get("/v1/health", func(c *zip.Ctx) error {
|
|
return c.JSON(200, map[string]string{"status": "ok", "transport": "zap"})
|
|
})
|
|
|
|
const addr = "127.0.0.1:19653"
|
|
go func() { _ = app.ListenZAP(addr) }()
|
|
defer func() { _ = app.Shutdown() }()
|
|
|
|
// Wait for the ZAP listener to accept (bounded).
|
|
waitReachable(t, addr)
|
|
|
|
req := fasthttp.AcquireRequest()
|
|
resp := fasthttp.AcquireResponse()
|
|
defer fasthttp.ReleaseRequest(req)
|
|
defer fasthttp.ReleaseResponse(resp)
|
|
req.SetRequestURI("/v1/health")
|
|
req.Header.SetMethod(fasthttp.MethodGet)
|
|
|
|
tr := zaphttp.NewTransport(addr)
|
|
defer tr.CloseIdleConnections()
|
|
if err := tr.Do(req, resp); err != nil {
|
|
t.Fatalf("ZAP round-trip failed: %v", err)
|
|
}
|
|
|
|
if resp.StatusCode() != 200 {
|
|
t.Fatalf("status = %d, want 200", resp.StatusCode())
|
|
}
|
|
body := string(resp.Body())
|
|
if !strings.Contains(body, `"status":"ok"`) || !strings.Contains(body, `"transport":"zap"`) {
|
|
t.Fatalf("body over ZAP = %q, want the handler's JSON", body)
|
|
}
|
|
}
|
|
|
|
func waitReachable(t *testing.T, addr string) {
|
|
t.Helper()
|
|
tr := zaphttp.NewTransport(addr)
|
|
tr.SetDialTimeout(200 * time.Millisecond)
|
|
defer tr.CloseIdleConnections()
|
|
for i := 0; i < 50; i++ {
|
|
req := fasthttp.AcquireRequest()
|
|
resp := fasthttp.AcquireResponse()
|
|
req.SetRequestURI("/v1/health")
|
|
req.Header.SetMethod(fasthttp.MethodGet)
|
|
err := tr.Do(req, resp)
|
|
fasthttp.ReleaseRequest(req)
|
|
fasthttp.ReleaseResponse(resp)
|
|
if err == nil {
|
|
return
|
|
}
|
|
time.Sleep(40 * time.Millisecond)
|
|
}
|
|
t.Fatalf("ZAP listener at %s never became reachable", addr)
|
|
}
|