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).
67 lines
2.4 KiB
Go
67 lines
2.4 KiB
Go
package zip
|
|
|
|
import (
|
|
"github.com/gofiber/fiber/v3"
|
|
zaphttp "github.com/zap-proto/http"
|
|
)
|
|
|
|
// The transport layer: ONE fiber handler, served over TWO transports.
|
|
//
|
|
// ZAP (TLS 1.3 + post-quantum, gRPC's replacement) is the PRIMARY transport;
|
|
// plain HTTP is the optional EXTRA for human/REST/browser clients. Both serve
|
|
// the SAME `a.fiber.Handler()`, so every /v1 route is reachable identically
|
|
// over either — there is NO separate RPC surface to register, NO ordinal mux,
|
|
// NO per-endpoint wiring. This is the one-and-only-one-way model: your routes
|
|
// ARE the ZAP surface, exactly as they are the HTTP surface. (Supersedes the
|
|
// old zaprpc-registry ZAPListen stub — the routes replace the registry.)
|
|
|
|
// prepare installs the deferred routes (OpenAPI) before a listener starts.
|
|
// Shared by both transports so ZAP and HTTP expose the same surface.
|
|
func (a *App) prepare() { a.installOpenAPIRoutes() }
|
|
|
|
// ListenHTTP serves plain HTTP on addr and blocks. The optional EXTRA
|
|
// transport. (Was `Listen`; renamed for symmetry with ListenZAP — verb-first,
|
|
// transport-suffixed, the way Go stdlib names net.Listen/http.ListenAndServe.)
|
|
func (a *App) ListenHTTP(addr string) error {
|
|
a.prepare()
|
|
a.logger.Info("zip listening HTTP", "addr", addr)
|
|
return a.fiber.Listen(addr, fiber.ListenConfig{
|
|
DisableStartupMessage: a.cfg.DisableStartupMessage,
|
|
})
|
|
}
|
|
|
|
// ListenZAP serves the fiber handler over ZAP — the PRIMARY transport. Blocks
|
|
// until Shutdown. Every route registered on this App answers over ZAP with the
|
|
// same middleware, auth filters, and error handling as over HTTP.
|
|
func (a *App) ListenZAP(addr string) error {
|
|
a.prepare()
|
|
s := &zaphttp.Server{Addr: addr, Handler: a.fiber.Handler()}
|
|
a.zapMu.Lock()
|
|
a.zap = s
|
|
a.zapMu.Unlock()
|
|
a.logger.Info("zip listening ZAP", "addr", addr)
|
|
return s.ListenAndServe()
|
|
}
|
|
|
|
// Serve runs ZAP (primary) and, when httpAddr != "", HTTP (extra) concurrently,
|
|
// returning the first listener error. The normal way to bring a zip binary up
|
|
// on both transports.
|
|
func (a *App) Serve(zapAddr, httpAddr string) error {
|
|
errc := make(chan error, 2)
|
|
go func() { errc <- a.ListenZAP(zapAddr) }()
|
|
if httpAddr != "" {
|
|
go func() { errc <- a.ListenHTTP(httpAddr) }()
|
|
}
|
|
return <-errc
|
|
}
|
|
|
|
// closeZAP stops the ZAP listener if one is running. Called from Shutdown.
|
|
func (a *App) closeZAP() {
|
|
a.zapMu.Lock()
|
|
s := a.zap
|
|
a.zapMu.Unlock()
|
|
if s != nil {
|
|
_ = s.Close()
|
|
}
|
|
}
|