cached gateway routing

This commit is contained in:
Stephan D
2026-02-20 15:38:22 +01:00
parent bc2bc3770d
commit 671ccc55a0
23 changed files with 777 additions and 23 deletions

View File

@@ -35,6 +35,41 @@ type envConfig struct {
const defaultConsumerBufferSize = 1024
func sanitizeNATSURL(rawURL string) string {
if rawURL == "" {
return rawURL
}
parts := strings.Split(rawURL, ",")
sanitized := make([]string, 0, len(parts))
for _, part := range parts {
trimmed := strings.TrimSpace(part)
if trimmed == "" {
continue
}
if !strings.Contains(trimmed, "://") {
sanitized = append(sanitized, trimmed)
continue
}
parsed, err := url.Parse(trimmed)
if err != nil {
sanitized = append(sanitized, trimmed)
continue
}
if parsed.User == nil {
sanitized = append(sanitized, trimmed)
continue
}
sanitized = append(sanitized, parsed.Redacted())
}
if len(sanitized) == 0 {
return strings.TrimSpace(rawURL)
}
return strings.Join(sanitized, ",")
}
// loadEnv gathers and validates connection details from environment variables
// listed in the Settings struct. Invalid or missing values surface as a typed
// InvalidArgument error so callers can decide how to handle them.
@@ -109,6 +144,7 @@ func NewNatsBroker(logger mlogger.Logger, settings *nc.Settings) (*NatsBroker, e
}
natsURL = u.String()
}
sanitizedNATSURL := sanitizeNATSURL(natsURL)
opts := []nats.Option{
nats.Name(settings.NATSName),
@@ -120,7 +156,7 @@ func NewNatsBroker(logger mlogger.Logger, settings *nc.Settings) (*NatsBroker, e
zap.String("broker", settings.NATSName),
}
if conn != nil {
fields = append(fields, zap.String("connected_url", conn.ConnectedUrl()))
fields = append(fields, zap.String("connected_url", sanitizeNATSURL(conn.ConnectedUrl())))
}
if err != nil {
fields = append(fields, zap.Error(err))
@@ -132,7 +168,7 @@ func NewNatsBroker(logger mlogger.Logger, settings *nc.Settings) (*NatsBroker, e
zap.String("broker", settings.NATSName),
}
if conn != nil {
fields = append(fields, zap.String("connected_url", conn.ConnectedUrl()))
fields = append(fields, zap.String("connected_url", sanitizeNATSURL(conn.ConnectedUrl())))
}
l.Info("Reconnected to NATS", fields...)
}),
@@ -142,7 +178,7 @@ func NewNatsBroker(logger mlogger.Logger, settings *nc.Settings) (*NatsBroker, e
}
if conn != nil {
if url := conn.ConnectedUrl(); url != "" {
fields = append(fields, zap.String("connected_url", url))
fields = append(fields, zap.String("connected_url", sanitizeNATSURL(url)))
}
if err := conn.LastError(); err != nil {
fields = append(fields, zap.Error(err))
@@ -172,7 +208,7 @@ func NewNatsBroker(logger mlogger.Logger, settings *nc.Settings) (*NatsBroker, e
}
if res.nc, err = nats.Connect(natsURL, opts...); err != nil {
l.Error("Failed to connect to NATS", zap.String("url", natsURL), zap.Error(err))
l.Error("Failed to connect to NATS", zap.String("url", sanitizedNATSURL), zap.Error(err))
return nil, err
}
if res.js, err = res.nc.JetStream(); err != nil {
@@ -180,7 +216,7 @@ func NewNatsBroker(logger mlogger.Logger, settings *nc.Settings) (*NatsBroker, e
}
logger.Info("Connected to NATS", zap.String("broker", settings.NATSName),
zap.String("url", natsURL))
zap.String("url", sanitizedNATSURL))
return res, nil
}

View File

@@ -0,0 +1,58 @@
package natsb
import (
"strings"
"testing"
)
func TestSanitizeNATSURL(t *testing.T) {
t.Parallel()
t.Run("redacts single URL credentials", func(t *testing.T) {
t.Parallel()
raw := "nats://alice:supersecret@localhost:4222"
sanitized := sanitizeNATSURL(raw)
if strings.Contains(sanitized, "supersecret") {
t.Fatalf("expected password to be redacted, got %q", sanitized)
}
if !strings.Contains(sanitized, "alice:xxxxx@") {
t.Fatalf("expected redacted URL to keep username, got %q", sanitized)
}
})
t.Run("keeps URL without credentials unchanged", func(t *testing.T) {
t.Parallel()
raw := "nats://localhost:4222"
sanitized := sanitizeNATSURL(raw)
if sanitized != raw {
t.Fatalf("expected URL without credentials to remain unchanged, got %q", sanitized)
}
})
t.Run("redacts each URL in server list", func(t *testing.T) {
t.Parallel()
raw := " nats://alice:one@localhost:4222, nats://bob:two@localhost:4223 "
sanitized := sanitizeNATSURL(raw)
if strings.Contains(sanitized, "one") || strings.Contains(sanitized, "two") {
t.Fatalf("expected passwords to be redacted, got %q", sanitized)
}
if !strings.Contains(sanitized, "alice:xxxxx@") || !strings.Contains(sanitized, "bob:xxxxx@") {
t.Fatalf("expected both URLs to be redacted, got %q", sanitized)
}
})
t.Run("returns invalid URL as-is", func(t *testing.T) {
t.Parallel()
raw := "not a url"
sanitized := sanitizeNATSURL(raw)
if sanitized != raw {
t.Fatalf("expected invalid URL to remain unchanged, got %q", sanitized)
}
})
}