package server import ( "log/slog" "time" ) type serverOptions struct { addr string readTimeout time.Duration readHeaderTimeout time.Duration writeTimeout time.Duration idleTimeout time.Duration shutdownTimeout time.Duration logger *slog.Logger middlewares []Middleware onShutdown []func() } // Option configures a Server. type Option func(*serverOptions) // WithAddr sets the listen address. Default is ":8080". func WithAddr(addr string) Option { return func(o *serverOptions) { o.addr = addr } } // WithReadTimeout sets the maximum duration for reading the entire request. func WithReadTimeout(d time.Duration) Option { return func(o *serverOptions) { o.readTimeout = d } } // WithReadHeaderTimeout sets the maximum duration for reading request headers. func WithReadHeaderTimeout(d time.Duration) Option { return func(o *serverOptions) { o.readHeaderTimeout = d } } // WithWriteTimeout sets the maximum duration before timing out writes of the response. func WithWriteTimeout(d time.Duration) Option { return func(o *serverOptions) { o.writeTimeout = d } } // WithIdleTimeout sets the maximum amount of time to wait for the next request // when keep-alives are enabled. func WithIdleTimeout(d time.Duration) Option { return func(o *serverOptions) { o.idleTimeout = d } } // WithShutdownTimeout sets the maximum duration to wait for active connections // to close during graceful shutdown. Default is 15 seconds. func WithShutdownTimeout(d time.Duration) Option { return func(o *serverOptions) { o.shutdownTimeout = d } } // WithLogger sets the structured logger used by the server for lifecycle events. func WithLogger(l *slog.Logger) Option { return func(o *serverOptions) { o.logger = l } } // WithMiddleware appends server middlewares to the chain. // These are applied to the handler in the order given. func WithMiddleware(mws ...Middleware) Option { return func(o *serverOptions) { o.middlewares = append(o.middlewares, mws...) } } // WithOnShutdown registers a function to be called during graceful shutdown, // before the HTTP server begins draining connections. func WithOnShutdown(fn func()) Option { return func(o *serverOptions) { o.onShutdown = append(o.onShutdown, fn) } } // Defaults returns a production-ready set of options including standard // middleware (RequestID, Recovery, Logging), sensible timeouts, and the // provided logger. // // Middleware order: RequestID → Recovery → Logging → user handler. func Defaults(logger *slog.Logger) []Option { return []Option{ WithReadHeaderTimeout(10 * time.Second), WithIdleTimeout(120 * time.Second), WithShutdownTimeout(15 * time.Second), WithLogger(logger), WithMiddleware( RequestID(), Recovery(WithRecoveryLogger(logger)), Logging(logger), ), } }