mirror of
https://github.com/hanzoai/gateway.git
synced 2026-11-02 23:52:23 +00:00
Every import in this module now resolves to github.com/hanzoai/gateway/v2.
The 34 github.com/krakend/* + github.com/luraproject/lura modules that
supplied the engine and its components are vendored under internal/ and
their 91 packages rewritten onto our own path.
Why fold rather than mirror into 34 hanzoai/* repos:
- It removes the exposure outright. 34 rows leave 34 rows of go.sum to
reason about; zero modules leave nothing. `go list -m all` and go.sum
now contain no krakend/lura entry at all.
- Cross-references cannot go wrong. 28 of the 34 import lura (97 files
inside lura self-reference it). Mirroring means rewriting every one of
those to our lura, and a single miss silently links a SECOND copy of
lura into the binary. With one module that is structurally impossible.
- It creates no duplicates. These are lura-coupled gateway glue with no
consumer outside this binary; publishing 34 repos would be 34 new
things to maintain for zero second caller. internal/ makes that
guarantee mechanical — Go forbids importing it from outside this
module, so none of it can become a competing public package. Verified
no repo outside gateway imports any hanzoai/gateway/v2 subpackage.
Layout mirrors provenance so an upstream re-sync stays a diff:
luraproject/lura/v2 -> internal/lura (the engine, 20 pkgs)
krakend/krakend-<x> -> internal/plugin/<x> (28 components)
krakend/<x> -> internal/pkg/<x> (6 standalone libs)
This commit is PURELY MECHANICAL: 196 of the 197 vendored files are
byte-identical to their upstream original once the import rewrite is
applied. The single exception is bloomfilter's subpackage, which upstream
names `krakend` — the one package name that could not survive as-is; it
becomes internal/pkg/bloomfilter/register. Hand edits land separately in
the next commit so they are readable on their own.
Per `go mod vendor` semantics, dependencies' _test.go files are not
vendored. They test upstream code at a pinned version that we do not
modify, several cannot run at all from a module distribution (they need
TLS certs and compiled .so plugins upstream generates but never ships),
and one is a 100k-request stress test that exhausts the ephemeral port
range and fails every package running beside it. Fold integrity is proven
by the byte-diff above instead, which is the stronger check.
Preserved deliberately — each of these is behaviour, not branding:
- the `github.com/devopsfaith/krakend*` extra_config namespace strings
(35 of them). These are config-surface keys, not import paths;
renaming one silently stops that component finding its config. The
jose validator namespace backs `auth/validator` on 212 endpoints.
- core.KrakendVersion / KrakendUserAgent / the X-KRAKEND consts, whose
VALUES rebrand.go overwrites — that seam is unchanged.
- the KRAKEND_ koanf env prefix (a hardcoded upstream const).
- every vendored module's LICENSE (34 files, Apache-2.0/MIT).
The Makefile/CI -X paths move with the engine. An -X naming a symbol that
does not exist is silently ignored by the linker, so a stale path here
would have shipped an "undefined" version in the backend User-Agent and
X-Api-Version with a perfectly green build. Verified live:
`gateway version` reports 2.13.0, not undefined.
Verification (GOWORK=off CGO_ENABLED=0, both tag modes):
go build ./... OK go build -tags legacy ./... OK
go vet ./... clean go vet -tags legacy ./... clean
go test ./... 6/6 ok go test -tags legacy 5/5 ok
tests/ integration harness 47 fixtures pass
gateway check -c configs/{hanzo,lux}/gateway.json -> Syntax OK!
go list -m all | grep -iE 'krakend|lura' -> empty
go mod verify -> all modules verified
Co-authored-by: Hanzo Dev <[email protected]>
288 lines
11 KiB
Go
288 lines
11 KiB
Go
package dumper
|
|
|
|
import (
|
|
"net/http"
|
|
"sort"
|
|
|
|
"github.com/hanzoai/gateway/v2/internal/lura/config"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func New(cmd *cobra.Command, prefix string, verboseLevel int) Dumper {
|
|
return NewWithColors(cmd, prefix, verboseLevel, true)
|
|
}
|
|
|
|
func NewWithColors(cmd *cobra.Command, prefix string, verboseLevel int, enableColors bool) Dumper {
|
|
d := Dumper{
|
|
cmd: cmd,
|
|
checkDumpPrefix: prefix,
|
|
verboseLevel: verboseLevel,
|
|
}
|
|
if !enableColors {
|
|
return d
|
|
}
|
|
d.colorRed = ColorRed
|
|
d.colorGreen = ColorGreen
|
|
d.colorReset = ColorReset
|
|
d.colorBlue = ColorBlue
|
|
d.colorCyan = ColorCyan
|
|
d.colorYellow = ColorYellow
|
|
d.colorMagenta = ColorMagenta
|
|
d.colorWhite = ColorWhite
|
|
return d
|
|
}
|
|
|
|
type Dumper struct {
|
|
cmd *cobra.Command
|
|
checkDumpPrefix string
|
|
verboseLevel int
|
|
colorRed string
|
|
colorGreen string
|
|
colorReset string
|
|
colorBlue string
|
|
colorCyan string
|
|
colorYellow string
|
|
colorMagenta string
|
|
colorWhite string
|
|
}
|
|
|
|
func (c Dumper) Dump(v config.ServiceConfig) error {
|
|
c.cmd.Printf("%sGlobal settings%s\n", c.colorGreen, c.colorReset)
|
|
c.cmd.Printf("%sName: %s\n", c.checkDumpPrefix, v.Name)
|
|
c.cmd.Printf("%sVersion: %d\n", c.checkDumpPrefix, v.Version)
|
|
c.cmd.Printf("%sAddress: %s\n", c.checkDumpPrefix, v.Address)
|
|
c.cmd.Printf("%sPort: %d\n", c.checkDumpPrefix, v.Port)
|
|
|
|
if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sDefault cache TTL: %s\n", c.checkDumpPrefix, v.CacheTTL.String())
|
|
c.cmd.Printf("%sDefault timeout: %s\n", c.checkDumpPrefix, v.Timeout.String())
|
|
}
|
|
|
|
if len(v.Host) > 0 || c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sDefault backend hosts: %v\n", c.checkDumpPrefix, v.Host)
|
|
}
|
|
|
|
if c.verboseLevel > 2 {
|
|
c.cmd.Printf("%sRead timeout: %s\n", c.checkDumpPrefix, v.ReadTimeout.String())
|
|
c.cmd.Printf("%sWrite timeout: %s\n", c.checkDumpPrefix, v.WriteTimeout.String())
|
|
c.cmd.Printf("%sIdle timeout: %s\n", c.checkDumpPrefix, v.IdleTimeout.String())
|
|
c.cmd.Printf("%sRead header timeout: %s\n", c.checkDumpPrefix, v.ReadHeaderTimeout.String())
|
|
c.cmd.Printf("%sIdle connection timeout: %s\n", c.checkDumpPrefix, v.IdleConnTimeout.String())
|
|
c.cmd.Printf("%sResponse header timeout: %s\n", c.checkDumpPrefix, v.ResponseHeaderTimeout.String())
|
|
c.cmd.Printf("%sExpect continue timeout: %s\n", c.checkDumpPrefix, v.ExpectContinueTimeout.String())
|
|
c.cmd.Printf("%sDialer timeout: %s\n", c.checkDumpPrefix, v.DialerTimeout.String())
|
|
c.cmd.Printf("%sDialer fallback delay: %s\n", c.checkDumpPrefix, v.DialerFallbackDelay.String())
|
|
c.cmd.Printf("%sDialer keep alive: %s\n", c.checkDumpPrefix, v.DialerKeepAlive.String())
|
|
c.cmd.Printf("%sDisable keep alives: %v\n", c.checkDumpPrefix, v.DisableKeepAlives)
|
|
c.cmd.Printf("%sDisable compression: %v\n", c.checkDumpPrefix, v.DisableCompression)
|
|
c.cmd.Printf("%sMax idle connections: %d\n", c.checkDumpPrefix, v.MaxIdleConns)
|
|
c.cmd.Printf("%sMax idle connections per host: %d\n", c.checkDumpPrefix, v.MaxIdleConnsPerHost)
|
|
c.cmd.Printf("%sSequential start: %t\n", c.checkDumpPrefix, v.SequentialStart)
|
|
|
|
c.cmd.Printf("%sMax header bytes: %d\n", c.checkDumpPrefix, v.MaxHeaderBytes)
|
|
c.cmd.Printf("%sEcho endpoint enabled: %t\n", c.checkDumpPrefix, v.Echo)
|
|
c.cmd.Printf("%sDefault encoding strategy: %s\n", c.checkDumpPrefix, v.OutputEncoding)
|
|
c.cmd.Printf("%sDisable strict REST: %t\n", c.checkDumpPrefix, v.DisableStrictREST)
|
|
c.cmd.Printf("%sRun lura in debug mode: %t\n", c.checkDumpPrefix, v.Debug)
|
|
c.cmd.Printf("%sAllow insecure connections: %t\n", c.checkDumpPrefix, v.AllowInsecureConnections)
|
|
c.cmd.Printf("%sUseH2C: %t\n", c.checkDumpPrefix, v.UseH2C)
|
|
}
|
|
|
|
if v.TLS != nil {
|
|
c.cmd.Printf("%sTLS Disabled: %t\n", c.checkDumpPrefix, v.TLS.IsDisabled)
|
|
// TODO: update this with the new field `Keys`:
|
|
c.cmd.Printf("%sTLS Public key: %s\n", c.checkDumpPrefix, v.TLS.PublicKey)
|
|
c.cmd.Printf("%sTLS Private key: %s\n", c.checkDumpPrefix, v.TLS.PrivateKey)
|
|
c.cmd.Printf("%sTLS Enable MTLS: %t\n", c.checkDumpPrefix, v.TLS.EnableMTLS)
|
|
c.cmd.Printf("%sTLS Disable System CA Pool: %v\n", c.checkDumpPrefix, v.TLS.DisableSystemCaPool)
|
|
|
|
if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sTLS Min version: %s\n", c.checkDumpPrefix, v.TLS.MinVersion)
|
|
c.cmd.Printf("%sTLS Max version: %s\n", c.checkDumpPrefix, v.TLS.MaxVersion)
|
|
}
|
|
if c.verboseLevel > 2 {
|
|
c.cmd.Printf("%sTLS Curve preferences: %v\n", c.checkDumpPrefix, v.TLS.CurvePreferences)
|
|
c.cmd.Printf("%sTLS Prefer server cipher suites: %v\n", c.checkDumpPrefix, v.TLS.PreferServerCipherSuites)
|
|
c.cmd.Printf("%sTLS Cipher suites: %v\n", c.checkDumpPrefix, v.TLS.CipherSuites)
|
|
}
|
|
} else if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%s%sNo TLS section defined%s\n", c.checkDumpPrefix, c.colorRed, c.colorReset)
|
|
}
|
|
|
|
if v.ClientTLS != nil {
|
|
c.cmd.Printf("%sClient TLS Allow Insecure Connections: %v\n", c.checkDumpPrefix, v.ClientTLS.AllowInsecureConnections)
|
|
c.cmd.Printf("%sClient TLS Disable System CA Pool: %v\n", c.checkDumpPrefix, v.ClientTLS.DisableSystemCaPool)
|
|
|
|
if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sClient TLS Min version: %s\n", c.checkDumpPrefix, v.ClientTLS.MinVersion)
|
|
c.cmd.Printf("%sClient TLS Max version: %s\n", c.checkDumpPrefix, v.ClientTLS.MaxVersion)
|
|
}
|
|
if c.verboseLevel > 2 {
|
|
c.cmd.Printf("%sClient TLS Curve preferences: %v\n", c.checkDumpPrefix, v.ClientTLS.CurvePreferences)
|
|
c.cmd.Printf("%sClient TLS Cipher suites: %v\n", c.checkDumpPrefix, v.ClientTLS.CipherSuites)
|
|
}
|
|
}
|
|
|
|
if v.Plugin != nil {
|
|
c.cmd.Printf("%sFolder: %s\n", c.checkDumpPrefix, v.Plugin.Folder)
|
|
c.cmd.Printf("%sPattern: %s\n", c.checkDumpPrefix, v.Plugin.Pattern)
|
|
} else if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%s%sNo Plugin section defined%s\n", c.checkDumpPrefix, c.colorRed, c.colorReset)
|
|
}
|
|
|
|
if c.verboseLevel > 1 || len(v.ExtraConfig) > 0 {
|
|
c.cmd.Printf("%s%d global component configuration(s):%s\n", c.colorGreen, len(v.ExtraConfig), c.colorReset)
|
|
c.dumpExtraConfig(v.ExtraConfig, "")
|
|
}
|
|
|
|
c.cmd.Printf("%s%d API endpoint(s):%s\n", c.colorGreen, len(v.Endpoints), c.colorReset)
|
|
for _, endpoint := range v.Endpoints {
|
|
c.dumpEndpoint(endpoint)
|
|
}
|
|
|
|
c.cmd.Printf("%s%d async agent(s):%s\n", c.colorGreen, len(v.AsyncAgents), c.colorReset)
|
|
for _, agent := range v.AsyncAgents {
|
|
c.dumpAgent(agent)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c Dumper) dumpAgent(agent *config.AsyncAgent) {
|
|
c.cmd.Printf("%s- %s%s%s\n", c.checkDumpPrefix, c.colorCyan, agent.Name, c.colorReset)
|
|
|
|
if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sEncoding: %s\n", c.checkDumpPrefix, agent.Encoding)
|
|
|
|
c.cmd.Printf("%sConsumer Timeout: %s\n", c.checkDumpPrefix, agent.Consumer.Timeout.String())
|
|
c.cmd.Printf("%sConsumer Workers: %d\n", c.checkDumpPrefix, agent.Consumer.Workers)
|
|
c.cmd.Printf("%sConsumer Topic: %s\n", c.checkDumpPrefix, agent.Consumer.Topic)
|
|
c.cmd.Printf("%sConsumer Max Rate: %f\n", c.checkDumpPrefix, agent.Consumer.MaxRate)
|
|
|
|
c.cmd.Printf("%sConnection Max Retries: %d\n", c.checkDumpPrefix, agent.Connection.MaxRetries)
|
|
c.cmd.Printf("%sConnection Backoff Strategy: %s\n", c.checkDumpPrefix, agent.Connection.BackoffStrategy)
|
|
c.cmd.Printf("%sConnection Health Interval: %s\n", c.checkDumpPrefix, agent.Connection.HealthInterval.String())
|
|
}
|
|
|
|
if c.verboseLevel > 1 || len(agent.ExtraConfig) > 0 {
|
|
c.cmd.Printf("%s%s%d agent component configuration(s):%s\n", c.checkDumpPrefix, c.colorGreen, len(agent.ExtraConfig), c.colorReset)
|
|
c.dumpExtraConfig(agent.ExtraConfig, c.checkDumpPrefix)
|
|
}
|
|
|
|
c.cmd.Printf("%s%sConnecting to %d backend(s):%s\n", c.checkDumpPrefix, c.colorGreen, len(agent.Backend), c.colorReset)
|
|
for _, backend := range agent.Backend {
|
|
c.dumpBackend(backend)
|
|
}
|
|
}
|
|
|
|
func (c Dumper) dumpEndpoint(endpoint *config.EndpointConfig) {
|
|
c.cmd.Printf("%s- %s%s%s %s%s\n", c.checkDumpPrefix, c.methodColor(endpoint.Method), endpoint.Method, c.colorCyan, endpoint.Endpoint, c.colorReset)
|
|
c.cmd.Printf("%sTimeout: %s\n", c.checkDumpPrefix, endpoint.Timeout.String())
|
|
|
|
if c.verboseLevel > 1 || len(endpoint.QueryString) > 0 {
|
|
c.cmd.Printf("%sQueryString: %v\n", c.checkDumpPrefix, endpoint.QueryString)
|
|
}
|
|
|
|
if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sCacheTTL: %s\n", c.checkDumpPrefix, endpoint.CacheTTL.String())
|
|
c.cmd.Printf("%sHeaders to pass: %v\n", c.checkDumpPrefix, endpoint.HeadersToPass)
|
|
c.cmd.Printf("%sOutputEncoding: %s\n", c.checkDumpPrefix, endpoint.OutputEncoding)
|
|
}
|
|
|
|
if c.verboseLevel > 1 || endpoint.ConcurrentCalls > 1 {
|
|
c.cmd.Printf("%sConcurrent calls: %d\n", c.checkDumpPrefix, endpoint.ConcurrentCalls)
|
|
}
|
|
|
|
if c.verboseLevel > 1 || len(endpoint.ExtraConfig) > 0 {
|
|
c.cmd.Printf("%s%s%d endpoint component configuration(s):%s\n", c.checkDumpPrefix, c.colorGreen, len(endpoint.ExtraConfig), c.colorReset)
|
|
c.dumpExtraConfig(endpoint.ExtraConfig, c.checkDumpPrefix)
|
|
}
|
|
|
|
c.cmd.Printf("%s%sConnecting to %d backend(s):%s\n", c.checkDumpPrefix, c.colorGreen, len(endpoint.Backend), c.colorReset)
|
|
for _, backend := range endpoint.Backend {
|
|
c.dumpBackend(backend)
|
|
}
|
|
}
|
|
|
|
func (c Dumper) dumpBackend(backend *config.Backend) {
|
|
prefix := c.checkDumpPrefix + c.checkDumpPrefix
|
|
c.cmd.Printf("%s[+] %s%s%s %s%s\n", prefix, c.methodColor(backend.Method), backend.Method, c.colorCyan, backend.URLPattern, c.colorReset)
|
|
c.cmd.Printf("%sTimeout: %s\n", prefix, backend.Timeout.String())
|
|
c.cmd.Printf("%sHosts: %v\n", prefix, backend.Host)
|
|
|
|
if c.verboseLevel > 1 {
|
|
c.cmd.Printf("%sConcurrent calls: %d\n", prefix, backend.ConcurrentCalls)
|
|
c.cmd.Printf("%sHost sanitization disabled: %v\n", prefix, backend.HostSanitizationDisabled)
|
|
c.cmd.Printf("%sTarget: %s\n", prefix, backend.Target)
|
|
c.cmd.Printf("%sDeny: %v, Allow: %v\n", prefix, backend.DenyList, backend.AllowList)
|
|
c.cmd.Printf("%sMapping: %+v\n", prefix, backend.Mapping)
|
|
c.cmd.Printf("%sGroup: %s\n", prefix, backend.Group)
|
|
c.cmd.Printf("%sEncoding: %s\n", prefix, backend.Encoding)
|
|
c.cmd.Printf("%sIs collection: %+v\n", prefix, backend.IsCollection)
|
|
c.cmd.Printf("%sSD: %+v\n", prefix, backend.SD)
|
|
c.cmd.Printf("%sSD scheme: %s\n", prefix, backend.SDScheme)
|
|
c.cmd.Printf("%sHeaders to pass: %v\n", prefix, backend.HeadersToPass)
|
|
c.cmd.Printf("%sQuery strings to pass: %v\n", prefix, backend.QueryStringsToPass)
|
|
}
|
|
|
|
if c.verboseLevel > 1 || len(backend.ExtraConfig) > 0 {
|
|
c.cmd.Printf("%s%s%d backend component configuration(s):%s\n", prefix, c.colorGreen, len(backend.ExtraConfig), c.colorReset)
|
|
c.dumpExtraConfig(backend.ExtraConfig, prefix)
|
|
}
|
|
c.cmd.Println("")
|
|
}
|
|
|
|
func (c Dumper) dumpExtraConfig(cfg config.ExtraConfig, prefix string) {
|
|
var keys []string
|
|
|
|
for k := range cfg {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
c.cmd.Printf("%s%s- %s%s\n", prefix, c.colorYellow, k, c.colorReset)
|
|
if c.verboseLevel > 1 {
|
|
switch s := cfg[k].(type) {
|
|
case map[string]interface{}:
|
|
for i, v := range s {
|
|
c.cmd.Printf("\t%s%s: %+v\n", prefix, i, v)
|
|
}
|
|
case []interface{}:
|
|
c.cmd.Printf("\t%s: %+v\n", prefix, s)
|
|
default:
|
|
c.cmd.Printf("\t%s: %+v\n", prefix, s)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c Dumper) methodColor(s string) string {
|
|
switch s {
|
|
case http.MethodGet:
|
|
return c.colorBlue
|
|
case http.MethodPost:
|
|
return c.colorCyan
|
|
case http.MethodPut:
|
|
return c.colorYellow
|
|
case http.MethodDelete:
|
|
return c.colorRed
|
|
case http.MethodPatch:
|
|
return c.colorGreen
|
|
case http.MethodHead:
|
|
return c.colorMagenta
|
|
case http.MethodOptions:
|
|
return c.colorWhite
|
|
}
|
|
return ""
|
|
}
|
|
|
|
const (
|
|
ColorGreen = "\033[32;1m"
|
|
ColorWhite = "\033[37;1m"
|
|
ColorYellow = "\033[33;1m"
|
|
ColorRed = "\033[31;1m"
|
|
ColorBlue = "\033[34;1m"
|
|
ColorMagenta = "\033[36;1m"
|
|
ColorCyan = "\033[36;1m"
|
|
ColorReset = "\033[0m"
|
|
)
|