server

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 25, 2026 License: MIT Imports: 12 Imported by: 0

README

go-server

A minimal, production-ready, reusable HTTP server foundation for Go web services using Chi router and slog structured logging.

This package provides everything you need to spin up a secure, observable, and gracefully shutdown-capable web server with almost zero boilerplate.

Features

  • Automatic TLS support (via env vars)
  • Graceful shutdown on SIGINT and SIGTERM
  • Structured JSON logging with log/slog
  • Request ID generation and propagation
  • Panic recovery with stack traces
  • Structured access logging (method, path, duration, status, bytes, request_id)
  • Built-in /healthz and /readyz endpoints
  • Configurable timeouts (read, write, idle, shutdown)
  • Functional options for clean configuration
  • Full request-scoped contextual logging via slog.Logger.With()

Installation

go get github.com/derekmwright/web/server

Quick Start

package main

import (
    "os"

    "github.com/go-chi/chi/v5"
    "github.com/derekmwright/web/server"
)

func main() {
    r := chi.NewRouter()

    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello from your new service!"))
    })

    // Optional: custom logger, timeouts, etc.
    srv := server.New(
        server.WithRouter(r),
        // server.WithLogger(customLogger),
        // server.WithShutdownTimeout(20 * time.Second),
    )

    if err := srv.Start(); err != nil {
        srv.Log.Error("server stopped with error", "error", err)
        os.Exit(1)
    }
}

That's it — your service is now running with full production features.

Configuration (Environment Variables)

Variable Description Default
APP_SERVER_ADDR Listen address (host:port) :8080
APP_SERVER_TLS_KEY_FILE Path to TLS private key (none)
APP_SERVER_TLS_CERT_FILE Path to TLS certificate (none)

TLS is automatically enabled if both key and cert files exist and are readable.

Logging

  • Uses log/slog with JSON output by default
  • All logs include timestamps and levels
  • Access logs include duration, status, bytes, and request_id
  • Panics are recovered and logged with full stack trace
  • Request-scoped logging: use server.LoggerFromContext(r.Context()) in handlers for logs that automatically include request_id, method, path, etc.
Example Handler with Request-Scoped Logging
func protectedHandler(w http.ResponseWriter, r *http.Request) {
    log := server.LoggerFromContext(r.Context())

    log.Info("handling protected request", "action", "load_dashboard")

    // All logs here automatically include request_id, method, path, etc.
    log.Debug("fetching user data", "user_id", 123)

    w.Write([]byte("Protected content"))
}

Middleware Stack (Applied by Default)

  1. Panic recovery (with structured error logging)
  2. Request ID generation (X-Request-ID header)
  3. Structured request logging

You can override the router completely with WithRouter() — middleware will still apply unless you replace the router after New().

Options

server.WithLogger(logger *slog.Logger)
server.WithRouter(router chi.Router)
server.WithReadTimeout(duration time.Duration)
server.WithWriteTimeout(duration time.Duration)
server.WithIdleTimeout(duration time.Duration)
server.WithShutdownTimeout(duration time.Duration)

Health Endpoints

  • GET /healthz → returns "ok" (200)
  • GET /readyz → returns "ready" (200)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HealthHandler

func HealthHandler(w http.ResponseWriter, r *http.Request)

func LoggerFromContext

func LoggerFromContext(ctx context.Context) *slog.Logger

func MiddlewareLogging

func MiddlewareLogging(log *slog.Logger) func(http.Handler) http.Handler

func MiddlewareRecovery

func MiddlewareRecovery(log *slog.Logger) func(http.Handler) http.Handler

func MiddlewareRequestID

func MiddlewareRequestID() func(http.Handler) http.Handler

func ReadinessHandler

func ReadinessHandler(w http.ResponseWriter, r *http.Request)

Types

type Config

type Config struct {
	Addr        string
	TLSKeyFile  string
	TLSCertFile string
}

type Option

type Option func(*Server)

func WithIdleTimeout

func WithIdleTimeout(d time.Duration) Option

func WithLogger

func WithLogger(logger *slog.Logger) Option

func WithMiddleware

func WithMiddleware(mw func(http.Handler) http.Handler) Option

func WithReadTimeout

func WithReadTimeout(d time.Duration) Option

func WithRouter

func WithRouter(router chi.Router) Option

func WithShutdownTimeout

func WithShutdownTimeout(d time.Duration) Option

func WithWriteTimeout

func WithWriteTimeout(d time.Duration) Option

type Server

type Server struct {
	Log    *slog.Logger
	Router chi.Router
	// contains filtered or unexported fields
}

func New

func New(opts ...Option) *Server

func (*Server) LoggerWithContext

func (s *Server) LoggerWithContext(ctx context.Context) *slog.Logger

func (*Server) Start

func (s *Server) Start() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL