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.
114 lines
4.1 KiB
Go
114 lines
4.1 KiB
Go
package ekko
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/labstack/echo/v4/middleware"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
slogecho "github.com/samber/slog-echo"
|
|
)
|
|
|
|
// Ekko represents an enhanced Echo web server with pre-configured middleware stack.
|
|
// It encapsulates server configuration, middleware options, and lifecycle management
|
|
// for NTP Pool web services. Use New() with functional options to configure.
|
|
type Ekko struct {
|
|
name string
|
|
prom prometheus.Registerer
|
|
port int
|
|
routeFn func(e *echo.Echo) error
|
|
logFilters []slogecho.Filter
|
|
otelmiddleware echo.MiddlewareFunc
|
|
gzipConfig *middleware.GzipConfig
|
|
extraTrustOptions []echo.TrustOption
|
|
|
|
writeTimeout time.Duration
|
|
readHeaderTimeout time.Duration
|
|
}
|
|
|
|
// RouteFn defines a function type for configuring Echo routes and handlers.
|
|
// It receives a configured Echo instance and should register all application
|
|
// routes, middleware, and handlers. Return an error to abort server startup.
|
|
type RouteFn func(e *echo.Echo) error
|
|
|
|
// WithPort sets the HTTP server port. This option is required when using Start().
|
|
// The port should be available and the process should have permission to bind to it.
|
|
func WithPort(port int) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.port = port
|
|
}
|
|
}
|
|
|
|
// WithPrometheus enables Prometheus metrics collection using the provided registerer.
|
|
// Metrics include HTTP request duration, request count, and response size histograms.
|
|
// The service name is used as the metrics subsystem for namespacing.
|
|
func WithPrometheus(reg prometheus.Registerer) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.prom = reg
|
|
}
|
|
}
|
|
|
|
// WithEchoSetup configures application routes and handlers via a setup function.
|
|
// The provided function receives the configured Echo instance after all middleware
|
|
// is applied and should register routes, custom middleware, and handlers.
|
|
func WithEchoSetup(rfn RouteFn) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.routeFn = rfn
|
|
}
|
|
}
|
|
|
|
// WithLogFilters configures access log filtering to reduce log noise.
|
|
// Filters can exclude specific paths, methods, or status codes from access logs.
|
|
// Useful for excluding health checks, metrics endpoints, and other high-frequency requests.
|
|
func WithLogFilters(f []slogecho.Filter) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.logFilters = f
|
|
}
|
|
}
|
|
|
|
// WithOtelMiddleware replaces the default OpenTelemetry middleware with a custom implementation.
|
|
// The default middleware provides distributed tracing for all requests. Use this option
|
|
// when you need custom trace configuration or want to disable tracing entirely.
|
|
func WithOtelMiddleware(mw echo.MiddlewareFunc) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.otelmiddleware = mw
|
|
}
|
|
}
|
|
|
|
// WithWriteTimeout configures the HTTP server write timeout.
|
|
// This is the maximum duration before timing out writes of the response.
|
|
// Default is 60 seconds. Should be longer than expected response generation time.
|
|
func WithWriteTimeout(t time.Duration) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.writeTimeout = t
|
|
}
|
|
}
|
|
|
|
// WithReadHeaderTimeout configures the HTTP server read header timeout.
|
|
// This is the amount of time allowed to read request headers.
|
|
// Default is 30 seconds. Should be sufficient for slow clients and large headers.
|
|
func WithReadHeaderTimeout(t time.Duration) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.readHeaderTimeout = t
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
// By default, gzip compression is enabled with standard settings.
|
|
// Use this option to customize compression level, skip patterns, or disable compression.
|
|
func WithGzipConfig(gzipConfig *middleware.GzipConfig) func(*Ekko) {
|
|
return func(ek *Ekko) {
|
|
ek.gzipConfig = gzipConfig
|
|
}
|
|
}
|