mirror of
https://github.com/hanzoai/gateway.git
synced 2026-11-02 23:52:23 +00:00
* 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.
120 lines
4.0 KiB
Go
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)
|