2 Commits
v0.8.0 ... main

Author SHA1 Message Date
82de580879 feat(ekko): add WithTrustOptions for CDN IP trust configuration
Allow callers to append additional echo.TrustOption values to the
default IP extraction configuration. This enables trusting CDN IP
ranges (e.g. Fastly) when extracting client IPs from X-Forwarded-For.
2026-03-08 18:31:44 -07:00
92b202037a fix(ekko): store service name and add fallback for Server header
The name parameter passed to ekko.New() was never stored on the struct,
causing the HTTP Server header to be malformed (e.g. "/vdev-snapshot+hash"
instead of "warmform/vdev-snapshot+hash").

Store the name in the struct literal and add a fallback that derives the
name from debug.ReadBuildInfo() if an empty string is passed.
2026-03-08 17:41:41 -07:00
2 changed files with 36 additions and 7 deletions

View File

@@ -34,6 +34,8 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"runtime/debug"
"strings"
"time" "time"
"github.com/labstack/echo-contrib/echoprometheus" "github.com/labstack/echo-contrib/echoprometheus"
@@ -70,6 +72,7 @@ import (
// - WithGzipConfig(): Custom gzip compression settings // - WithGzipConfig(): Custom gzip compression settings
func New(name string, options ...func(*Ekko)) (*Ekko, error) { func New(name string, options ...func(*Ekko)) (*Ekko, error) {
ek := &Ekko{ ek := &Ekko{
name: name,
writeTimeout: 60 * time.Second, writeTimeout: 60 * time.Second,
readHeaderTimeout: 30 * time.Second, readHeaderTimeout: 30 * time.Second,
} }
@@ -77,6 +80,20 @@ func New(name string, options ...func(*Ekko)) (*Ekko, error) {
for _, o := range options { for _, o := range options {
o(ek) o(ek)
} }
if ek.name == "" {
if bi, ok := debug.ReadBuildInfo(); ok && bi.Main.Path != "" {
if idx := strings.LastIndex(bi.Main.Path, "/"); idx >= 0 {
ek.name = bi.Main.Path[idx+1:]
} else {
ek.name = bi.Main.Path
}
}
if ek.name == "" {
ek.name = "ekko-app"
}
}
return ek, nil return ek, nil
} }
@@ -146,6 +163,7 @@ func (ek *Ekko) setup(ctx context.Context) (*echo.Echo, error) {
echo.TrustLinkLocal(false), echo.TrustLinkLocal(false),
echo.TrustPrivateNet(true), echo.TrustPrivateNet(true),
} }
trustOptions = append(trustOptions, ek.extraTrustOptions...)
e.IPExtractor = echo.ExtractIPFromXFFHeader(trustOptions...) e.IPExtractor = echo.ExtractIPFromXFFHeader(trustOptions...)
if ek.otelmiddleware == nil { if ek.otelmiddleware == nil {

View File

@@ -13,13 +13,14 @@ import (
// It encapsulates server configuration, middleware options, and lifecycle management // It encapsulates server configuration, middleware options, and lifecycle management
// for NTP Pool web services. Use New() with functional options to configure. // for NTP Pool web services. Use New() with functional options to configure.
type Ekko struct { type Ekko struct {
name string name string
prom prometheus.Registerer prom prometheus.Registerer
port int port int
routeFn func(e *echo.Echo) error routeFn func(e *echo.Echo) error
logFilters []slogecho.Filter logFilters []slogecho.Filter
otelmiddleware echo.MiddlewareFunc otelmiddleware echo.MiddlewareFunc
gzipConfig *middleware.GzipConfig gzipConfig *middleware.GzipConfig
extraTrustOptions []echo.TrustOption
writeTimeout time.Duration writeTimeout time.Duration
readHeaderTimeout time.Duration readHeaderTimeout time.Duration
@@ -92,6 +93,16 @@ func WithReadHeaderTimeout(t time.Duration) func(*Ekko) {
} }
} }
// WithTrustOptions appends additional trust options to the default IP extraction
// configuration. These options are applied after the built-in trust settings
// (loopback trusted, link-local untrusted, private networks trusted) when
// extracting client IPs from the X-Forwarded-For header.
func WithTrustOptions(opts ...echo.TrustOption) func(*Ekko) {
return func(ek *Ekko) {
ek.extraTrustOptions = append(ek.extraTrustOptions, opts...)
}
}
// WithGzipConfig provides custom gzip compression configuration. // WithGzipConfig provides custom gzip compression configuration.
// By default, gzip compression is enabled with standard settings. // By default, gzip compression is enabled with standard settings.
// Use this option to customize compression level, skip patterns, or disable compression. // Use this option to customize compression level, skip patterns, or disable compression.