mirror of
https://github.com/hanzoai/gateway.git
synced 2026-10-30 15:04:44 +00:00
Prose only, plus one config knob. Applied to comment lines exclusively, so import paths, the exported lura symbols (core.Krakend*), the X-KRAKEND header const, the KRAKEND_ koanf prefix and the devopsfaith/* extra_config namespace keys were structurally out of reach of the rewrite. `KRAKEND_ZAP_LISTEN` -> `GATEWAY_ZAP_LISTEN`. LLM.md listed this as pinned to the koanf env prefix; it is not. koanf owns `KRAKEND_<KEY>` for config-file key overrides, but this var is the fork's own knob read by direct os.Getenv, so it belongs with GATEWAY_LISTEN / GATEWAY_SHUTDOWN_TIMEOUT. Nothing in k8s/ or configs/ sets it, so nothing to migrate -- one prefix for our knobs. `TestGatewayConfig_NoKrakendAudience` -> `TestGatewayConfig_NoJWTAudience`. Kept deliberately, and now documented with the reason rather than a bare "never rebrand": the two `rebrand.go` files (they are the de-branders -- they must name what they strip), the Makefile schema-rewrite pipeline (same role), the negative-assertion lists in brand_test.go / production_headers_test.go (those are the regression guard that FAILS if the brand ever reaches a Server header -- deleting the token would delete the protection), LICENSE + NOTICE attribution, deps.sh's module-name grep, and the upstream image address in mirror-images.yml. Two LLM.md rows were wrong and are corrected: the extra_config namespace keys live in the `aliases` map in cmd/gateway/main_legacy.go, not in configs/*/gateway.json -- the shipped configs use only the friendly aliases and are already brand-free; and the ingress cross-reference described a `DefaultRootName` that fork no longer has. Verified: both builds, all unit packages under -tags legacy, and the legacy integration harness with CI's skip list.
60 lines
2.7 KiB
Go
60 lines
2.7 KiB
Go
// Copyright © 2026 Hanzo AI. MIT License.
|
|
|
|
package gateway
|
|
|
|
import "strings"
|
|
|
|
// brandForHost resolves a request Host to its white-label brand id for the
|
|
// Server response header. The gateway is the shared multi-brand edge — it fronts
|
|
// api.hanzo.ai, api.lux.network, api.zoo.ngo, ... from one binary — so the Server
|
|
// header cannot be a single hardcoded brand; it must be the brand of the request
|
|
// Host, or a neutral default when no brand domain matches.
|
|
//
|
|
// A Host at or under a brand's registrable domain resolves to that brand; the
|
|
// longest matching domain wins; the port is stripped and the compare is
|
|
// case-insensitive. Returns "" when nothing matches, so the caller supplies its
|
|
// own neutral default (NeutralServerBrand).
|
|
//
|
|
// This mirrors the canonical platform registry in hanzoai/cloud (brand.go /
|
|
// BrandForHostOK). The gateway keeps its own copy because its pinned cloud does
|
|
// not yet export BrandForHostOK and, more fundamentally, zip's white-label
|
|
// middleware rides the zap-proto/fiber fork that the pinned cloud predates — a
|
|
// coordinated cloud+zip bump is out of scope for a response-header change. When
|
|
// that alignment lands (or a shared brand module is extracted) this folds into
|
|
// that one home.
|
|
func brandForHost(host string) string {
|
|
host = strings.ToLower(strings.TrimSpace(host))
|
|
if i := strings.IndexByte(host, ':'); i >= 0 {
|
|
host = host[:i]
|
|
}
|
|
// A fully-qualified Host may carry a trailing root dot ("api.lux.network.");
|
|
// strip it so the suffix match still resolves the brand instead of failing to
|
|
// neutral. Mirrors cloud/brand.go BrandForHostOK.
|
|
host = strings.TrimSuffix(host, ".")
|
|
best, bestLen := "", -1
|
|
for _, bd := range brandDomains {
|
|
if (host == bd.domain || strings.HasSuffix(host, "."+bd.domain)) && len(bd.domain) > bestLen {
|
|
best, bestLen = bd.brand, len(bd.domain)
|
|
}
|
|
}
|
|
return best
|
|
}
|
|
|
|
// brandDomains mirrors cloud/brand.go's per-brand Domain + AltDomains.
|
|
var brandDomains = []struct{ brand, domain string }{
|
|
{"hanzo", "hanzo.ai"}, {"hanzo", "hanzo.cloud"}, {"hanzo", "hanzo.app"},
|
|
{"lux", "lux.network"}, {"lux", "lux.cloud"},
|
|
{"zoo", "zoo.ngo"}, {"zoo", "zoo.network"}, {"zoo", "zoo.cloud"},
|
|
{"pars", "pars.network"}, {"pars", "pars.ai"},
|
|
{"bootnode", "bootno.de"},
|
|
}
|
|
|
|
// NeutralServerBrand is the Server value when a request Host matches no brand
|
|
// (internal k8s probes, direct-IP hits). Brand-neutral and honest about the role
|
|
// without ever naming the framework (fasthttp / fiber / zip / the legacy engine).
|
|
const NeutralServerBrand = "gateway"
|
|
|
|
// hstsPolicy is the Strict-Transport-Security value: two years, subdomains
|
|
// included — the Stripe/Cloudflare/GitHub production floor.
|
|
const hstsPolicy = "max-age=63072000; includeSubDomains"
|