Help us shape the future of Go! Take the 2026 Go Developer Survey

server

package
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

README

Server Package

Production-ready HTTP server manager with graceful shutdown, request draining, and comprehensive TLS/HTTPS support.

Features

✅ Multiple Server Management - Run multiple HTTP/HTTPS servers concurrently ✅ Graceful Shutdown - Handles SIGINT/SIGTERM with request draining ✅ Automatic Request Rejection - New requests get 503 during shutdown ✅ Health & Readiness Endpoints - Kubernetes-ready health checks ✅ Shutdown Callbacks - Register cleanup functions (DB, cache, metrics) ✅ Comprehensive TLS Support:

  • Certificate files (production)
  • Self-signed certificates (development/testing)
  • Let's Encrypt / AutoTLS (automatic certificate management) ✅ GZIP Compression - Optional response compression ✅ Panic Recovery - Automatic panic recovery middleware ✅ Configurable Timeouts - Read, write, idle, drain, and shutdown timeouts

Quick Start

Single Server
import "github.com/bitechdev/ResolveSpec/pkg/server"

// Create server manager
mgr := server.NewManager()

// Add server
_, err := mgr.Add(server.Config{
    Name:    "api-server",
    Host:    "localhost",
    Port:    8080,
    Handler: myRouter,
    GZIP:    true,
})

// Start and wait for shutdown signal
if err := mgr.ServeWithGracefulShutdown(); err != nil {
    log.Fatal(err)
}
Multiple Servers
mgr := server.NewManager()

// Public API
mgr.Add(server.Config{
    Name:    "public-api",
    Port:    8080,
    Handler: publicRouter,
})

// Admin API
mgr.Add(server.Config{
    Name:    "admin-api",
    Port:    8081,
    Handler: adminRouter,
})

// Start all and wait
mgr.ServeWithGracefulShutdown()

HTTPS/TLS Configuration

Option 1: Certificate Files (Production)
mgr.Add(server.Config{
    Name:    "https-server",
    Host:    "0.0.0.0",
    Port:    443,
    Handler: handler,
    SSLCert: "/etc/ssl/certs/server.crt",
    SSLKey:  "/etc/ssl/private/server.key",
})
Option 2: Self-Signed Certificate (Development)
mgr.Add(server.Config{
    Name:          "dev-server",
    Host:          "localhost",
    Port:          8443,
    Handler:       handler,
    SelfSignedSSL: true,  // Auto-generates certificate
})
Option 3: Let's Encrypt / AutoTLS (Production)
mgr.Add(server.Config{
    Name:            "prod-server",
    Host:            "0.0.0.0",
    Port:            443,
    Handler:         handler,
    AutoTLS:         true,
    AutoTLSDomains:  []string{"example.com", "www.example.com"},
    AutoTLSEmail:    "admin@example.com",
    AutoTLSCacheDir: "./certs-cache",  // Certificate cache directory
})

Configuration

server.Config{
    // Basic configuration
    Name:        "my-server",        // Server name (required)
    Host:        "0.0.0.0",          // Bind address
    Port:        8080,               // Port (required)
    Handler:     myRouter,           // HTTP handler (required)
    Description: "My API server",    // Optional description

    // Features
    GZIP: true,                      // Enable GZIP compression

    // TLS/HTTPS (choose one option)
    SSLCert:         "/path/to/cert.pem",  // Certificate file
    SSLKey:          "/path/to/key.pem",   // Key file
    SelfSignedSSL:   false,                // Auto-generate self-signed cert
    AutoTLS:         false,                // Let's Encrypt
    AutoTLSDomains:  []string{},           // Domains for AutoTLS
    AutoTLSEmail:    "",                   // Email for Let's Encrypt
    AutoTLSCacheDir: "./certs-cache",      // Cert cache directory

    // Timeouts
    ShutdownTimeout: 30 * time.Second,     // Max shutdown time
    DrainTimeout:    25 * time.Second,     // Request drain timeout
    ReadTimeout:     15 * time.Second,     // Request read timeout
    WriteTimeout:    15 * time.Second,     // Response write timeout
    IdleTimeout:     60 * time.Second,     // Idle connection timeout
}

Graceful Shutdown

mgr := server.NewManager()

// Add servers...

// This blocks until SIGINT/SIGTERM
mgr.ServeWithGracefulShutdown()
Manual Control
mgr := server.NewManager()

// Add and start servers
mgr.StartAll()

// Later... stop gracefully
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

if err := mgr.StopAllWithContext(ctx); err != nil {
    log.Printf("Shutdown error: %v", err)
}
Shutdown Callbacks

Register cleanup functions to run during shutdown:

// Close database
mgr.RegisterShutdownCallback(func(ctx context.Context) error {
    log.Println("Closing database...")
    return db.Close()
})

// Flush metrics
mgr.RegisterShutdownCallback(func(ctx context.Context) error {
    log.Println("Flushing metrics...")
    return metrics.Flush(ctx)
})

// Close cache
mgr.RegisterShutdownCallback(func(ctx context.Context) error {
    log.Println("Closing cache...")
    return cache.Close()
})

Health Checks

Adding Health Endpoints
instance, _ := mgr.Add(server.Config{
    Name:    "api-server",
    Port:    8080,
    Handler: router,
})

// Add health endpoints to your router
router.HandleFunc("/health", instance.HealthCheckHandler())
router.HandleFunc("/ready", instance.ReadinessHandler())
Health Endpoint

Returns server health status:

Healthy (200 OK):

{"status":"healthy"}

Shutting Down (503 Service Unavailable):

{"status":"shutting_down"}
Readiness Endpoint

Returns readiness with in-flight request count:

Ready (200 OK):

{"ready":true,"in_flight_requests":12}

Not Ready (503 Service Unavailable):

{"ready":false,"reason":"shutting_down"}

Shutdown Behavior

When a shutdown signal (SIGINT/SIGTERM) is received:

  1. Mark as shutting down → New requests get 503
  2. Execute callbacks → Run cleanup functions
  3. Drain requests → Wait up to DrainTimeout for in-flight requests
  4. Shutdown servers → Close listeners and connections
Time   Event
─────────────────────────────────────────
0s     Signal received: SIGTERM
       ├─ Mark servers as shutting down
       ├─ Reject new requests (503)
       └─ Execute shutdown callbacks

1s     Callbacks complete
       └─ Start draining requests...

2s     In-flight: 50 requests
3s     In-flight: 32 requests
4s     In-flight: 12 requests
5s     In-flight: 3 requests
6s     In-flight: 0 requests ✓
       └─ All requests drained

6s     Shutdown servers
7s     All servers stopped ✓

Server Management

Get Server Instance
instance, err := mgr.Get("api-server")
if err != nil {
    log.Fatal(err)
}

// Check status
fmt.Printf("Address: %s\n", instance.Addr())
fmt.Printf("Name: %s\n", instance.Name())
fmt.Printf("In-flight: %d\n", instance.InFlightRequests())
fmt.Printf("Shutting down: %v\n", instance.IsShuttingDown())
List All Servers
instances := mgr.List()
for _, instance := range instances {
    fmt.Printf("Server: %s at %s\n", instance.Name(), instance.Addr())
}
Remove Server
// Stop and remove a server
if err := mgr.Remove("api-server"); err != nil {
    log.Printf("Error removing server: %v", err)
}
Restart All Servers
// Gracefully restart all servers
if err := mgr.RestartAll(); err != nil {
    log.Printf("Error restarting: %v", err)
}

Kubernetes Integration

Deployment with Probes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: app
        image: myapp:latest
        ports:
        - containerPort: 8080

        # Liveness probe
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 10

        # Readiness probe
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

        # Graceful shutdown
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 5"]

        env:
        - name: SHUTDOWN_TIMEOUT
          value: "30"

      # Allow time for graceful shutdown
      terminationGracePeriodSeconds: 35

Docker Compose

version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SHUTDOWN_TIMEOUT=30
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 10s
      timeout: 5s
      retries: 3
    stop_grace_period: 35s

Complete Example

package main

import (
    "context"
    "log"
    "net/http"
    "time"

    "github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
    // Create server manager
    mgr := server.NewManager()

    // Register shutdown callbacks
    mgr.RegisterShutdownCallback(func(ctx context.Context) error {
        log.Println("Cleanup: Closing database...")
        // return db.Close()
        return nil
    })

    // Create router
    router := http.NewServeMux()
    router.HandleFunc("/api/data", dataHandler)

    // Add server
    instance, err := mgr.Add(server.Config{
        Name:            "api-server",
        Host:            "0.0.0.0",
        Port:            8080,
        Handler:         router,
        GZIP:            true,
        ShutdownTimeout: 30 * time.Second,
        DrainTimeout:    25 * time.Second,
    })
    if err != nil {
        log.Fatal(err)
    }

    // Add health endpoints
    router.HandleFunc("/health", instance.HealthCheckHandler())
    router.HandleFunc("/ready", instance.ReadinessHandler())

    // Start and wait for shutdown
    log.Println("Starting server on :8080")
    if err := mgr.ServeWithGracefulShutdown(); err != nil {
        log.Printf("Server stopped: %v", err)
    }

    log.Println("Server shutdown complete")
}

func dataHandler(w http.ResponseWriter, r *http.Request) {
    time.Sleep(100 * time.Millisecond) // Simulate work
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"message":"success"}`))
}

Testing Graceful Shutdown

Test Script
#!/bin/bash

# Start server in background
./myapp &
SERVER_PID=$!

# Wait for server to start
sleep 2

# Send requests
for i in {1..10}; do
    curl http://localhost:8080/api/data &
done

# Wait a bit
sleep 1

# Send shutdown signal
kill -TERM $SERVER_PID

# Try more requests (should get 503)
curl -v http://localhost:8080/api/data

# Wait for server to stop
wait $SERVER_PID
echo "Server stopped gracefully"

Best Practices

  1. Set appropriate timeouts

    • DrainTimeout < ShutdownTimeout
    • ShutdownTimeout < Kubernetes terminationGracePeriodSeconds
  2. Use shutdown callbacks for:

    • Database connections
    • Message queues
    • Metrics flushing
    • Cache shutdown
    • Background workers
  3. Health checks

    • Use /health for liveness (is app alive?)
    • Use /ready for readiness (can app serve traffic?)
  4. Load balancer considerations

    • Set preStop hook in Kubernetes (5-10s delay)
    • Allows load balancer to deregister before shutdown
  5. HTTPS in production

    • Use AutoTLS for public-facing services
    • Use certificate files for enterprise PKI
    • Use self-signed only for development/testing
  6. Monitoring

    • Track in-flight requests in metrics
    • Alert on slow drains
    • Monitor shutdown duration

Troubleshooting

Shutdown Takes Too Long
// Increase drain timeout
config.DrainTimeout = 60 * time.Second
config.ShutdownTimeout = 65 * time.Second
Requests Timing Out
// Increase write timeout
config.WriteTimeout = 30 * time.Second
Certificate Issues
// Verify certificate files exist and are readable
if _, err := os.Stat(config.SSLCert); err != nil {
    log.Fatalf("Certificate not found: %v", err)
}

// For AutoTLS, ensure:
// - Port 443 is accessible
// - Domains resolve to server IP
// - Cache directory is writable
Debug Logging
import "github.com/bitechdev/ResolveSpec/pkg/logger"

// Enable debug logging
logger.SetLevel("debug")

API Reference

Manager Methods
  • NewManager() - Create new server manager
  • Add(cfg Config) - Register server instance
  • Get(name string) - Get server by name
  • Remove(name string) - Stop and remove server
  • StartAll() - Start all registered servers
  • StopAll() - Stop all servers gracefully
  • StopAllWithContext(ctx) - Stop with timeout
  • RestartAll() - Restart all servers
  • List() - Get all server instances
  • ServeWithGracefulShutdown() - Start and block until shutdown
  • RegisterShutdownCallback(cb) - Register cleanup function
Instance Methods
  • Start() - Start the server
  • Stop(ctx) - Stop gracefully
  • Addr() - Get server address
  • Name() - Get server name
  • HealthCheckHandler() - Get health handler
  • ReadinessHandler() - Get readiness handler
  • InFlightRequests() - Get in-flight count
  • IsShuttingDown() - Check shutdown status
  • Wait() - Block until shutdown complete

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Name        string
	Host        string
	Port        int
	Description string

	// Handler is the http.Handler (e.g., a router) to be served.
	Handler http.Handler

	// GZIP compression support
	GZIP bool

	// HTTP2 enables HTTP/2 with the Extended CONNECT protocol (RFC 8441) for WebSocket support.
	// Requires TLS; pair with SSLCert/SSLKey, SelfSignedSSL, or AutoTLS.
	HTTP2 bool

	// TLS/HTTPS configuration options (mutually exclusive)
	// Option 1: Provide certificate and key files directly
	SSLCert string
	SSLKey  string

	// Option 2: Use self-signed certificate (for development/testing)
	// Generates a self-signed certificate automatically if no SSLCert/SSLKey provided
	SelfSignedSSL bool

	// Option 3: Use Let's Encrypt / Certbot for automatic TLS
	// AutoTLS enables automatic certificate management via Let's Encrypt
	AutoTLS bool
	// AutoTLSDomains specifies the domains for Let's Encrypt certificates
	AutoTLSDomains []string
	// AutoTLSCacheDir specifies where to cache certificates (default: "./certs-cache")
	AutoTLSCacheDir string
	// AutoTLSEmail is the email for Let's Encrypt registration (optional but recommended)
	AutoTLSEmail string

	// PanicHandler is called when a request handler panics.
	// If nil, the default middleware.PanicRecovery is used (logs, records metric, returns 500).
	PanicHandler func(w http.ResponseWriter, r *http.Request, rcv any)

	// Graceful shutdown configuration
	// ShutdownTimeout is the maximum time to wait for graceful shutdown
	// Default: 30 seconds
	ShutdownTimeout time.Duration

	// DrainTimeout is the time to wait for in-flight requests to complete
	// before forcing shutdown. Default: 25 seconds
	DrainTimeout time.Duration

	// ReadTimeout is the maximum duration for reading the entire request
	// Default: 15 seconds
	ReadTimeout time.Duration

	// WriteTimeout is the maximum duration before timing out writes of the response
	// Default: 15 seconds
	WriteTimeout time.Duration

	// IdleTimeout is the maximum amount of time to wait for the next request
	// Default: 60 seconds
	IdleTimeout time.Duration
}

Config holds the configuration for a single web server instance.

func FromConfigInstanceToServerConfig added in v1.0.11

func FromConfigInstanceToServerConfig(sic *config.ServerInstanceConfig, handler http.Handler) Config

FromConfigInstanceToServerConfig converts a config.ServerInstanceConfig to server.Config The handler must be provided separately as it cannot be serialized

type Instance added in v0.0.122

type Instance interface {
	// Start begins serving requests. This method should be non-blocking and
	// run the server in a separate goroutine.
	Start() error

	// Stop gracefully shuts down the server without interrupting any active connections.
	// It accepts a context to allow for a timeout.
	Stop(ctx context.Context) error

	// Addr returns the network address the server is listening on.
	Addr() string

	// Name returns the server instance name.
	Name() string

	// HealthCheckHandler returns a handler that responds to health checks.
	// Returns 200 OK when healthy, 503 Service Unavailable when shutting down.
	HealthCheckHandler() http.HandlerFunc

	// ReadinessHandler returns a handler for readiness checks.
	// Includes in-flight request count.
	ReadinessHandler() http.HandlerFunc

	// InFlightRequests returns the current number of in-flight requests.
	InFlightRequests() int64

	// IsShuttingDown returns true if the server is shutting down.
	IsShuttingDown() bool

	// Wait blocks until shutdown is complete.
	Wait()
}

Instance defines the interface for a single server instance. It abstracts the underlying http.Server, allowing for easier management and testing.

type Manager added in v0.0.122

type Manager interface {
	// Add registers a new server instance based on the provided configuration.
	// The server is not started until StartAll or Start is called on the instance.
	Add(cfg Config) (Instance, error)

	// Get returns a server instance by its name.
	Get(name string) (Instance, error)

	// Remove stops and removes a server instance by its name.
	Remove(name string) error

	// StartAll starts all registered server instances that are not already running.
	StartAll() error

	// StopAll gracefully shuts down all running server instances.
	// Executes shutdown callbacks and drains in-flight requests.
	StopAll() error

	// StopAllWithContext gracefully shuts down all running server instances with a context.
	StopAllWithContext(ctx context.Context) error

	// RestartAll gracefully restarts all running server instances.
	RestartAll() error

	// List returns all registered server instances.
	List() []Instance

	// ServeWithGracefulShutdown starts all servers and blocks until a shutdown signal is received.
	// It handles SIGINT and SIGTERM signals and performs graceful shutdown with callbacks.
	ServeWithGracefulShutdown() error

	// RegisterShutdownCallback registers a callback to be called during shutdown.
	// Useful for cleanup tasks like closing database connections, flushing metrics, etc.
	RegisterShutdownCallback(cb ShutdownCallback)
}

Manager defines the interface for a server manager. It is responsible for managing the lifecycle of multiple server instances.

Example (Basic)

ExampleManager_basic demonstrates basic server manager usage

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
	// Create a server manager
	mgr := server.NewManager()

	// Define a simple handler
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		fmt.Fprintln(w, "Hello from server!")
	})

	// Add an HTTP server
	_, err := mgr.Add(server.Config{
		Name:    "api-server",
		Host:    "localhost",
		Port:    8080,
		Handler: handler,
		GZIP:    true, // Enable GZIP compression
	})
	if err != nil {
		log.Fatal(err)
	}

	// Start all servers
	if err := mgr.StartAll(); err != nil {
		log.Fatal(err)
	}

	// Server is now running...
	// When done, stop gracefully
	if err := mgr.StopAll(); err != nil {
		log.Fatal(err)
	}
}
Example (GracefulShutdown)

ExampleManager_gracefulShutdown demonstrates graceful shutdown with callbacks

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
	mgr := server.NewManager()

	// Register shutdown callbacks for cleanup tasks
	mgr.RegisterShutdownCallback(func(ctx context.Context) error {
		fmt.Println("Closing database connections...")
		// Close your database here
		return nil
	})

	mgr.RegisterShutdownCallback(func(ctx context.Context) error {
		fmt.Println("Flushing metrics...")
		// Flush metrics here
		return nil
	})

	// Add server with custom timeouts
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// Simulate some work
		time.Sleep(100 * time.Millisecond)
		fmt.Fprintln(w, "Done!")
	})

	_, err := mgr.Add(server.Config{
		Name:            "api-server",
		Host:            "localhost",
		Port:            8080,
		Handler:         handler,
		ShutdownTimeout: 30 * time.Second, // Max time for shutdown
		DrainTimeout:    25 * time.Second, // Time to wait for in-flight requests
		ReadTimeout:     10 * time.Second,
		WriteTimeout:    10 * time.Second,
		IdleTimeout:     120 * time.Second,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Start servers and block until shutdown signal (SIGINT/SIGTERM)
	// This will automatically handle graceful shutdown with callbacks
	if err := mgr.ServeWithGracefulShutdown(); err != nil {
		fmt.Printf("Shutdown completed: %v\n", err)
	}
}
Example (HealthChecks)

ExampleManager_healthChecks demonstrates health and readiness endpoints

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
	mgr := server.NewManager()

	// Create a router with health endpoints
	mux := http.NewServeMux()
	mux.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Data endpoint")
	})

	// Add server
	instance, err := mgr.Add(server.Config{
		Name:    "api-server",
		Host:    "localhost",
		Port:    8080,
		Handler: mux,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Add health and readiness endpoints
	mux.HandleFunc("/health", instance.HealthCheckHandler())
	mux.HandleFunc("/ready", instance.ReadinessHandler())

	// Start the server
	if err := mgr.StartAll(); err != nil {
		log.Fatal(err)
	}

	// Health check returns:
	// - 200 OK with {"status":"healthy"} when healthy
	// - 503 Service Unavailable with {"status":"shutting_down"} when shutting down

	// Readiness check returns:
	// - 200 OK with {"ready":true,"in_flight_requests":N} when ready
	// - 503 Service Unavailable with {"ready":false,"reason":"shutting_down"} when shutting down

	// Cleanup
	mgr.StopAll()
}
Example (Https)

ExampleManager_https demonstrates HTTPS configurations

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
	mgr := server.NewManager()
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Secure connection!")
	})

	// Option 1: Use certificate files
	_, err := mgr.Add(server.Config{
		Name:    "https-server-files",
		Host:    "localhost",
		Port:    8443,
		Handler: handler,
		SSLCert: "/path/to/cert.pem",
		SSLKey:  "/path/to/key.pem",
	})
	if err != nil {
		log.Fatal(err)
	}

	// Option 2: Self-signed certificate (for development)
	_, err = mgr.Add(server.Config{
		Name:          "https-server-self-signed",
		Host:          "localhost",
		Port:          8444,
		Handler:       handler,
		SelfSignedSSL: true,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Option 3: Let's Encrypt / AutoTLS (for production)
	_, err = mgr.Add(server.Config{
		Name:            "https-server-letsencrypt",
		Host:            "0.0.0.0",
		Port:            443,
		Handler:         handler,
		AutoTLS:         true,
		AutoTLSDomains:  []string{"example.com", "www.example.com"},
		AutoTLSEmail:    "admin@example.com",
		AutoTLSCacheDir: "./certs-cache",
	})
	if err != nil {
		log.Fatal(err)
	}

	// Start all servers
	if err := mgr.StartAll(); err != nil {
		log.Fatal(err)
	}

	// Cleanup
	mgr.StopAll()
}
Example (Monitoring)

ExampleManager_monitoring demonstrates monitoring server state

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
	mgr := server.NewManager()

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(50 * time.Millisecond) // Simulate work
		fmt.Fprintln(w, "Done")
	})

	instance, err := mgr.Add(server.Config{
		Name:    "api-server",
		Host:    "localhost",
		Port:    8080,
		Handler: handler,
	})
	if err != nil {
		log.Fatal(err)
	}

	if err := mgr.StartAll(); err != nil {
		log.Fatal(err)
	}

	// Check server status
	fmt.Printf("Server address: %s\n", instance.Addr())
	fmt.Printf("Server name: %s\n", instance.Name())
	fmt.Printf("Is shutting down: %v\n", instance.IsShuttingDown())
	fmt.Printf("In-flight requests: %d\n", instance.InFlightRequests())

	// Cleanup
	mgr.StopAll()

	// Wait for complete shutdown
	instance.Wait()
}
Example (MultipleServers)

ExampleManager_multipleServers demonstrates running multiple servers

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/bitechdev/ResolveSpec/pkg/server"
)

func main() {
	mgr := server.NewManager()

	// Public API server
	publicHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Public API")
	})
	_, err := mgr.Add(server.Config{
		Name:    "public-api",
		Host:    "0.0.0.0",
		Port:    8080,
		Handler: publicHandler,
		GZIP:    true,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Admin API server (different port)
	adminHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Admin API")
	})
	_, err = mgr.Add(server.Config{
		Name:    "admin-api",
		Host:    "localhost",
		Port:    8081,
		Handler: adminHandler,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Metrics server (internal only)
	metricsHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Metrics data")
	})
	_, err = mgr.Add(server.Config{
		Name:    "metrics",
		Host:    "127.0.0.1",
		Port:    9090,
		Handler: metricsHandler,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Start all servers at once
	if err := mgr.StartAll(); err != nil {
		log.Fatal(err)
	}

	// Get specific server instance
	publicInstance, err := mgr.Get("public-api")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Public API running on: %s\n", publicInstance.Addr())

	// List all servers
	instances := mgr.List()
	fmt.Printf("Running %d servers\n", len(instances))

	// Stop all servers gracefully (in parallel)
	if err := mgr.StopAll(); err != nil {
		log.Fatal(err)
	}
}

func NewManager added in v0.0.122

func NewManager() Manager

NewManager creates a new server manager.

type ShutdownCallback

type ShutdownCallback func(context.Context) error

ShutdownCallback is a function called during graceful shutdown.

Directories

Path Synopsis
Package quickproxy provides a small reverse-proxy layer that tries a set of configured upstream targets first, and falls back to a caller-supplied http.Handler (typically static file serving) when the upstream is unreachable or returns 404.
Package quickproxy provides a small reverse-proxy layer that tries a set of configured upstream targets first, and falls back to a caller-supplied http.Handler (typically static file serving) when the upstream is unreachable or returns 404.

Jump to

Keyboard shortcuts

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