Files
gateway/rebrand.go
zeekayandGitHub 96d53c8f28 chore(rebrand): v2.13.0 — de-kraken gateway (strip KrakenD branding) (#10)
* chore(rebrand): strip KrakenD-branded HTTP response headers

Adds a BrandingMiddleware that rewrites every X-KRAKEND*/X-Krakend-Completed
header emitted by the upstream lura SDK into Hanzo-branded equivalents
(X-Powered-By, X-Gateway-Completed). Also reassigns the lura package-level
vars (KrakendUserAgent, KrakendHeaderValue, CompleteResponseHeaderName) in
init() so outbound backend User-Agent carries the Hanzo brand instead of
"KrakenD Version x.y".

* chore(rebrand): rename CLI strings from KrakenD to hanzoai/gateway

Adds a rebrandCLI() pass that mutates the krakend-cobra command tree after
build: renames root command to "gateway", swaps short/long/example strings
to Hanzo equivalents, replaces the version subcommand output, strips the
KrakenD ASCII logo from the help template, rewrites the lint schema URL
to gateway.hanzo.ai, and recursively rewrites kraken references in every
subcommand's help text and flag usage strings.

* chore(rebrand): migrate test spec expectations from X-Krakend-Completed to X-Gateway-Completed

Updates all 59 integration-test fixture specs to assert on the new
X-Gateway-Completed response header and the hanzoai/gateway User-Agent
emitted by the rebranded server/backend pipeline. Also regenerates the
jwt_4 fixture's expected signed JWT to carry the gateway.hanzo.ai issuer.

* chore(rebrand): swap krakend.io schema URL and JWT issuer to gateway.hanzo.ai in configs

Updates tests/fixtures/gateway.json and all three deployed configs
(configs/hanzo, configs/liquidity, configs/lux) to reference the
gateway.hanzo.ai schema endpoint and emit gateway.hanzo.ai as the JWT
issuer for signed access tokens.

* chore(rebrand): vendor deps and rewrite kraken literals at build time

Switches the build target to go build -mod=vendor and adds a
vendor-rebrand step that rewrites every user-visible kraken string
literal in telemetry, metrics, CLI, and helper modules (krakend-otel,
krakend-opencensus, krakend-metrics, krakend-influx, krakend-cobra,
krakend-flexibleconfig, krakend-koanf, etc.). The embedded JSON Schema
is also rebranded in-place so gateway check --lint no longer exposes
krakend.io documentation URLs to users.

Third-party package paths under github.com/krakend/* and
github.com/devopsfaith/* remain intact — those are plugin registry
internals, never emitted at runtime.

* chore(rebrand): clean up KrakenD comment in executor

Minor doc-comment update so the RunServer comment no longer refers
to the upstream SDK by its legacy name.

* chore(rebrand): bump gateway to v2.13.0

Minor bump marking the first release that ships without any user-visible
KrakenD branding. Binary, HTTP headers, CLI output, config schema, and
test fixtures all carry the hanzoai/gateway brand.
2026-04-21 13:07:55 -07:00

120 lines
4.0 KiB
Go

// Package gateway rebrands every user-visible Lura/KrakenD identifier so that
// nothing a client or backend sees contains the string "krakend" or "KrakenD".
//
// Lura (the upstream SDK we build on) emits several hard-coded brand strings:
// - response header "X-KRAKEND"
// - response header "X-Krakend-Completed"
// - outbound backend User-Agent "KrakenD Version x.y"
// - core.KrakendHeaderValue "Version x.y"
//
// The response header name "X-KRAKEND" is a const in lura/core and cannot be
// reassigned at runtime; it is stripped and replaced by the BrandingMiddleware
// below. Everything else is a package-level var and is reassigned in init().
package gateway
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
"github.com/luraproject/lura/v2/core"
"github.com/luraproject/lura/v2/transport/http/server"
)
// BrandName is the canonical rebrand string emitted on responses and outbound
// backend calls. Overridable at build time via:
//
// -ldflags "-X github.com/hanzoai/gateway.BrandName=..."
var BrandName = "hanzoai/gateway"
// PoweredByHeader is the user-visible response header that replaces "X-KRAKEND".
const PoweredByHeader = "X-Powered-By"
// CompletedHeader is the user-visible response header that replaces
// "X-Krakend-Completed". It keeps the same "true" / "false" semantic so any
// client depending on the completion flag only needs to change the header key.
const CompletedHeader = "X-Gateway-Completed"
// legacyCompletedHeader is the hard-coded lura header name we need to strip.
const legacyCompletedHeader = "X-Krakend-Completed"
// legacyBrandHeader is the hard-coded lura header name (const in lura/core).
const legacyBrandHeader = "X-KRAKEND"
func init() {
// Reassign package-level vars in lura so that anything lura emits at runtime
// carries the Hanzo brand instead. core.KrakendVersion is set via ldflags in
// the Makefile; we pick up whatever value it holds at init time.
brandValue := fmt.Sprintf("%s Version %s", BrandName, core.KrakendVersion)
core.KrakendHeaderValue = brandValue
core.KrakendUserAgent = brandValue
server.UserAgentHeaderValue = []string{brandValue}
server.CompleteResponseHeaderName = CompletedHeader
}
// BrandingMiddleware strips any residual lura-emitted branding headers that
// leak through because their names are compile-time consts in lura/core, and
// replaces them with canonical Hanzo equivalents. Must run before the lura
// endpoint handler so the wrapped writer is in place by the time lura calls
// c.Header().
func BrandingMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer = &brandingWriter{ResponseWriter: c.Writer}
c.Next()
}
}
// brandingWriter wraps gin.ResponseWriter and rewrites branding headers at
// the last possible moment (WriteHeaderNow / Write / WriteString) before the
// response goes to the wire.
type brandingWriter struct {
gin.ResponseWriter
rewritten bool
}
func (w *brandingWriter) rewrite() {
if w.rewritten {
return
}
w.rewritten = true
h := w.ResponseWriter.Header()
if v := h.Get(legacyBrandHeader); v != "" {
h.Del(legacyBrandHeader)
h.Set(PoweredByHeader, v)
} else if h.Get(PoweredByHeader) == "" {
h.Set(PoweredByHeader, fmt.Sprintf("%s Version %s", BrandName, core.KrakendVersion))
}
// Defense in depth: if lura's var reassignment races with a hot path, strip
// the legacy completion header too.
if v := h.Get(legacyCompletedHeader); v != "" {
h.Del(legacyCompletedHeader)
if h.Get(CompletedHeader) == "" {
h.Set(CompletedHeader, v)
}
}
}
func (w *brandingWriter) WriteHeader(status int) {
w.rewrite()
w.ResponseWriter.WriteHeader(status)
}
func (w *brandingWriter) WriteHeaderNow() {
w.rewrite()
w.ResponseWriter.WriteHeaderNow()
}
func (w *brandingWriter) Write(p []byte) (int, error) {
w.rewrite()
return w.ResponseWriter.Write(p)
}
func (w *brandingWriter) WriteString(s string) (int, error) {
w.rewrite()
return w.ResponseWriter.WriteString(s)
}
// Ensure interface compliance.
var _ gin.ResponseWriter = (*brandingWriter)(nil)
var _ http.ResponseWriter = (*brandingWriter)(nil)