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).
3.3 KiB
Middleware reference
All zip middleware is a zip.Handler (not raw fiber.Handler) so the
user-facing handler signature stays uniform. Install via app.Use(...).
import "github.com/hanzoai/zip/middleware"
app.Use(
middleware.Recover(),
middleware.RequestID(),
middleware.Logger(app.Logger()),
)
Recover
Catches handler panics, logs the stack via luxfi/log, and returns a 500 JSON response. Always include first.
app.Use(middleware.Recover())
RequestID
Injects X-Request-Id. If the incoming request carries one, it's
preserved; otherwise zip mints a 16-byte hex value. Available via
c.RequestID().
app.Use(middleware.RequestID())
Logger
Wraps each request with a per-request luxfi/log child logger that
includes request_id, org, user. Logs the request line at
completion with status + dur_ms.
app.Use(middleware.Logger(app.Logger()))
Timeout
Per-request context deadline. Best-effort — Fiber's fasthttp-backed Ctx
does not natively propagate context cancellation through the request
lifetime; downstream code that consumes c.Context() (DB calls, HTTP
clients) gets the deadline.
app.Use(middleware.Timeout(30 * time.Second))
MaxBody
Rejects request bodies larger than n bytes with 413.
app.Use(middleware.MaxBody(1 << 20)) // 1 MiB
CORS
app.Use(middleware.CORS(middleware.CORSConfig{
AllowOrigins: []string{"https://app.hanzo.ai"},
AllowMethods: []string{"GET", "POST"},
AllowHeaders: []string{"Content-Type", "Authorization"},
AllowCreds: true,
MaxAge: 86400,
}))
Auth & StripIdentityHeaders — moved
Auth-specific middleware (JWT validation, identity-header stripping)
has moved to
github.com/hanzoai/gateway/middleware.
Rationale: JWT validation + identity-header minting are the gateway
subsystem's responsibility per HIP-0106. Other subsystems mounted
inside the unified cloud binary trust the gateway-minted X-Org-Id
header and do not re-validate JWTs themselves. The trust-assertion
helper gateway.AssertGatewayMinted(c) lets a downstream handler
defend against deployment misconfiguration where it is accidentally
exposed to direct (non-gateway) traffic.
RateLimit
Per-org (or per-IP fallback) in-memory token bucket. Single-pod only — multi-pod deployments must rate-limit at the gateway.
app.Use(middleware.RateLimit(middleware.RateLimitConfig{
Limit: 100,
Window: time.Minute,
}))
Telemetry
Plumbs request metrics to any O11ySink implementation. nil sink is a
no-op.
app.Use(middleware.Telemetry(myO11ySink))
Order
Recommended order for a Hanzo service behind hanzoai/gateway:
app.Use(
middleware.Recover(), // 1. always first
middleware.RequestID(), // 2. mint request id
middleware.Logger(app.Logger()), // 3. log with request id
middleware.Telemetry(o11y), // 4. metrics
middleware.RateLimit(rlCfg), // 5. limit
middleware.CORS(corsCfg), // 6. last — close to response
)
JWT validation + identity-header stripping are owned by the gateway
subsystem; see
github.com/hanzoai/gateway/middleware.