mirror of
https://github.com/nabbar/golib.git
synced 2025-12-24 11:51:02 +08:00
- config Server: change time duration to golib duration to simplify marshal string form - adjust test following update of config server - fix test in socket package to use BDD framework & gherkin form - adjust documentation & test Package HTTPServer: - Fix bug in PortUse & PortNotUse - Move function PortUse & PortNotUse as alone function - Add test & documentation - Unify test & documentation following other packages
655 lines
24 KiB
Go
655 lines
24 KiB
Go
/*
|
|
* MIT License
|
|
*
|
|
* Copyright (c) 2025 Nicolas JUHEL
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*
|
|
*/
|
|
|
|
// Package httpserver provides production-grade HTTP/HTTPS server management with comprehensive
|
|
// lifecycle control, configuration validation, TLS support, and integrated monitoring.
|
|
//
|
|
// # Overview
|
|
//
|
|
// This package offers a robust abstraction layer for managing HTTP and HTTPS servers in Go
|
|
// applications, emphasizing production readiness through comprehensive lifecycle management,
|
|
// declarative configuration with validation, optional TLS/SSL support, handler management,
|
|
// and built-in monitoring capabilities.
|
|
//
|
|
// The package is designed for scenarios requiring multiple server instances, dynamic
|
|
// configuration updates, graceful shutdowns, and centralized management through the pool
|
|
// subpackage. It extends the standard library's http.Server with additional features while
|
|
// maintaining compatibility with existing http.Handler implementations.
|
|
//
|
|
// # Design Philosophy
|
|
//
|
|
// The httpserver package follows these core design principles:
|
|
//
|
|
// 1. Configuration-Driven Architecture: Servers are defined through declarative configuration
|
|
// structures that are validated before use, enabling early detection of configuration errors
|
|
// and supporting externalized configuration from files, environment variables, or databases.
|
|
//
|
|
// 2. Lifecycle Management: Complete control over server start, stop, and restart operations
|
|
// with context-aware cancellation and graceful shutdown support. Servers can be started,
|
|
// stopped, and restarted programmatically with proper resource cleanup.
|
|
//
|
|
// 3. Thread-Safe Operations: All operations use atomic values and proper synchronization
|
|
// primitives, ensuring safe concurrent access from multiple goroutines without external
|
|
// locking requirements.
|
|
//
|
|
// 4. Production-Ready Features: Built-in monitoring integration, structured logging with
|
|
// field context, error handling with typed error codes, port conflict detection, and health
|
|
// checking capabilities.
|
|
//
|
|
// 5. Composable Design: The pool subpackage enables orchestration of multiple server instances
|
|
// as a unified entity, supporting filtering, batch operations, and aggregated monitoring.
|
|
//
|
|
// # Key Features
|
|
//
|
|
// Complete Lifecycle Control:
|
|
// - Context-aware Start, Stop, and Restart operations
|
|
// - Automatic resource cleanup and graceful shutdown
|
|
// - Uptime tracking and running state queries
|
|
// - Error tracking and recovery mechanisms
|
|
//
|
|
// Configuration Management:
|
|
// - Declarative configuration with struct tag validation
|
|
// - Deep cloning for safe configuration copies
|
|
// - Dynamic configuration updates with SetConfig
|
|
// - TLS/HTTPS configuration with certificate management
|
|
//
|
|
// Handler Management:
|
|
// - Dynamic handler registration via function callbacks
|
|
// - Multiple named handlers per server instance
|
|
// - Handler key-based routing for multi-handler scenarios
|
|
// - Fallback BadHandler for misconfigured servers
|
|
//
|
|
// TLS/HTTPS Support:
|
|
// - Integrated certificate management
|
|
// - Optional and mandatory TLS modes
|
|
// - Default TLS configuration inheritance
|
|
// - Automatic TLS detection and configuration
|
|
//
|
|
// Monitoring and Health Checking:
|
|
// - Built-in health check endpoints
|
|
// - Integration with monitor package
|
|
// - Server metrics and status information
|
|
// - Unique monitoring identifiers per server
|
|
//
|
|
// Pool Management (via pool subpackage):
|
|
// - Coordinate multiple server instances
|
|
// - Unified start/stop/restart operations
|
|
// - Advanced filtering by name, address, or URL
|
|
// - Configuration-based pool creation
|
|
//
|
|
// Thread-Safe Operations:
|
|
// - Atomic value storage for handlers and state
|
|
// - Concurrent access without explicit locking
|
|
// - Safe handler replacement during operation
|
|
// - Context-based synchronization
|
|
//
|
|
// Port Management:
|
|
// - Automatic port availability checking
|
|
// - Conflict detection before binding
|
|
// - Retry logic for port conflicts
|
|
// - Support for all interface binding (0.0.0.0)
|
|
//
|
|
// # Architecture
|
|
//
|
|
// The package consists of three main components working together:
|
|
//
|
|
// ┌────────────────────────────────────┐
|
|
// │ Application Layer │
|
|
// │ (HTTP Handlers & Routes) │
|
|
// └─────────────────┬──────────────────┘
|
|
// │
|
|
// ┌─────────▼─────────┐
|
|
// │ httpserver │
|
|
// │ Package API │
|
|
// └─────────┬─────────┘
|
|
// │
|
|
// ┌─────────────┼──────────────┐
|
|
// │ │ │
|
|
// ┌───▼───┐ ┌────▼────┐ ┌───▼────┐
|
|
// │Server │ │ Pool │ │ Types │
|
|
// │ │ │ │ │ │
|
|
// │Config │◄───┤ Manager │ │Handler │
|
|
// │Run │ │ Filter │ │Fields │
|
|
// │Monitor│ │ Clone │ │Const │
|
|
// └───┬───┘ └────┬────┘ └────────┘
|
|
// │ │
|
|
// └──────┬──────┘
|
|
// │
|
|
// ┌──────▼──────┐
|
|
// │ Go stdlib │
|
|
// │ http.Server │
|
|
// └─────────────┘
|
|
//
|
|
// Component Responsibilities:
|
|
//
|
|
// - Server: Core HTTP server implementation with lifecycle management
|
|
// - Config: Declarative configuration with validation and cloning
|
|
// - Pool: Multi-server orchestration and batch operations
|
|
// - Types: Shared type definitions and constants
|
|
// - Monitor: Health checking and metrics collection
|
|
// - Handler: Dynamic handler registration and management
|
|
//
|
|
// Data Flow:
|
|
// 1. Configuration is created and validated
|
|
// 2. Handlers are registered via function callbacks
|
|
// 3. Server instance is created from configuration
|
|
// 4. Start operation binds to port and begins serving
|
|
// 5. Handlers process incoming HTTP requests
|
|
// 6. Monitoring tracks health and metrics
|
|
// 7. Stop operation gracefully shuts down with timeout
|
|
//
|
|
// # Thread Safety Architecture
|
|
//
|
|
// The package uses multiple synchronization mechanisms for thread safety:
|
|
//
|
|
// Component | Mechanism | Concurrency Model
|
|
// --------------------|---------------------|----------------------------------
|
|
// Server State | atomic.Value | Lock-free reads, atomic writes
|
|
// Handler Registry | atomic.Value | Lock-free handler swapping
|
|
// Logger | atomic.Value | Thread-safe logging
|
|
// Runner | atomic.Value | Lifecycle synchronization
|
|
// Config Storage | context.Config | Context-based atomic storage
|
|
// Pool Map | sync.RWMutex | Multiple readers, exclusive writes
|
|
//
|
|
// All public methods are safe for concurrent use from multiple goroutines without
|
|
// external synchronization. Internal state updates use atomic operations to prevent
|
|
// data races.
|
|
//
|
|
// # Basic Usage
|
|
//
|
|
// Creating and starting a simple HTTP server:
|
|
//
|
|
// cfg := httpserver.Config{
|
|
// Name: "api-server",
|
|
// Listen: "127.0.0.1:8080",
|
|
// Expose: "http://localhost:8080",
|
|
// }
|
|
//
|
|
// cfg.RegisterHandlerFunc(func() map[string]http.Handler {
|
|
// mux := http.NewServeMux()
|
|
// mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
|
// w.WriteHeader(http.StatusOK)
|
|
// w.Write([]byte("OK"))
|
|
// })
|
|
// return map[string]http.Handler{"": mux}
|
|
// })
|
|
//
|
|
// if err := cfg.Validate(); err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
//
|
|
// srv, err := httpserver.New(cfg, nil)
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
//
|
|
// ctx := context.Background()
|
|
// if err := srv.Start(ctx); err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
// defer srv.Stop(ctx)
|
|
//
|
|
// # Configuration
|
|
//
|
|
// The Config structure defines all server parameters:
|
|
//
|
|
// type Config struct {
|
|
// Name string // Server identifier (required)
|
|
// Listen string // Bind address host:port (required)
|
|
// Expose string // Public URL (required)
|
|
// HandlerKey string // Handler map key (optional)
|
|
// Disabled bool // Disable flag for maintenance
|
|
// Monitor moncfg.Config // Monitoring configuration
|
|
// TLSMandatory bool // Require valid TLS
|
|
// TLS libtls.Config // TLS/certificate configuration
|
|
// ReadTimeout libdur.Duration // Request read timeout
|
|
// ReadHeaderTimeout libdur.Duration // Header read timeout
|
|
// WriteTimeout libdur.Duration // Response write timeout
|
|
// MaxHeaderBytes int // Maximum header size
|
|
// // ... HTTP/2 configuration fields ...
|
|
// }
|
|
//
|
|
// Configuration Validation:
|
|
//
|
|
// All configurations must pass validation before server creation:
|
|
// - Name: Must be non-empty string
|
|
// - Listen: Must be valid hostname:port format
|
|
// - Expose: Must be valid URL with scheme
|
|
// - TLS: Must be valid if TLSMandatory is true
|
|
//
|
|
// Configuration Methods:
|
|
// - Validate(): Comprehensive validation with detailed errors
|
|
// - Clone(): Deep copy of configuration
|
|
// - RegisterHandlerFunc(): Set handler function
|
|
// - SetDefaultTLS(): Set default TLS provider
|
|
// - SetContext(): Set parent context provider
|
|
// - Server(): Create server instance from config
|
|
//
|
|
// # Handler Management
|
|
//
|
|
// Handlers are registered via callback functions returning handler maps:
|
|
//
|
|
// handlerFunc := func() map[string]http.Handler {
|
|
// return map[string]http.Handler{
|
|
// "": defaultHandler, // Default handler
|
|
// "api": apiHandler, // Named handler for API
|
|
// "admin": adminHandler, // Named handler for admin
|
|
// }
|
|
// }
|
|
//
|
|
// cfg.RegisterHandlerFunc(handlerFunc)
|
|
//
|
|
// Handler Keys:
|
|
//
|
|
// The HandlerKey configuration field selects which handler from the map to use:
|
|
// - Empty string or "": Uses default handler
|
|
// - "api": Uses handler registered with "api" key
|
|
// - Custom keys: Application-specific handler selection
|
|
//
|
|
// Multiple servers can share the same handler function but use different keys
|
|
// to serve different handlers on different ports.
|
|
//
|
|
// # TLS/HTTPS Configuration
|
|
//
|
|
// Servers support optional and mandatory TLS/SSL:
|
|
//
|
|
// cfg := httpserver.Config{
|
|
// Name: "secure-api",
|
|
// Listen: "0.0.0.0:8443",
|
|
// Expose: "https://api.example.com",
|
|
// TLSMandatory: true,
|
|
// TLS: libtls.Config{
|
|
// CertPEM: "/path/to/cert.pem",
|
|
// KeyPEM: "/path/to/key.pem",
|
|
// // Additional TLS options...
|
|
// },
|
|
// }
|
|
//
|
|
// TLS Modes:
|
|
//
|
|
// - TLSMandatory = false: TLS is optional, server starts without certificates
|
|
// - TLSMandatory = true: Valid TLS config required, server fails to start without it
|
|
//
|
|
// TLS Configuration Inheritance:
|
|
//
|
|
// Servers can inherit from a default TLS configuration:
|
|
//
|
|
// cfg.SetDefaultTLS(func() libtls.TLSConfig {
|
|
// return defaultTLSConfig
|
|
// })
|
|
// cfg.TLS.InheritDefault = true
|
|
//
|
|
// # Lifecycle Management
|
|
//
|
|
// Servers implement the libsrv.Runner interface for lifecycle control:
|
|
//
|
|
// // Start server
|
|
// err := srv.Start(ctx)
|
|
// if err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
//
|
|
// // Check if running
|
|
// if srv.IsRunning() {
|
|
// log.Println("Server is running")
|
|
// }
|
|
//
|
|
// // Get uptime
|
|
// uptime := srv.Uptime()
|
|
// log.Printf("Server uptime: %v", uptime)
|
|
//
|
|
// // Stop gracefully
|
|
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
// defer cancel()
|
|
// err = srv.Stop(ctx)
|
|
//
|
|
// // Restart (stop then start)
|
|
// err = srv.Restart(ctx)
|
|
//
|
|
// Graceful Shutdown:
|
|
//
|
|
// The Stop method performs graceful shutdown:
|
|
// 1. Stops accepting new connections
|
|
// 2. Waits for active requests to complete (up to timeout)
|
|
// 3. Closes server resources and listeners
|
|
// 4. Returns error if shutdown exceeds timeout
|
|
//
|
|
// # Server Information
|
|
//
|
|
// Servers provide read-only access to configuration and state:
|
|
//
|
|
// name := srv.GetName() // Server identifier
|
|
// bind := srv.GetBindable() // Listen address
|
|
// expose := srv.GetExpose() // Public URL
|
|
// disabled := srv.IsDisable() // Disabled flag
|
|
// hasTLS := srv.IsTLS() // TLS enabled check
|
|
// cfg := srv.GetConfig() // Full configuration
|
|
//
|
|
// # Monitoring and Health Checking
|
|
//
|
|
// Servers integrate with the monitor package for health checks and metrics:
|
|
//
|
|
// // Get monitoring identifier
|
|
// monitorName := srv.MonitorName()
|
|
//
|
|
// // Get monitor with health checks and metrics
|
|
// monitor, err := srv.Monitor(versionInfo)
|
|
// if err != nil {
|
|
// log.Printf("Monitor error: %v", err)
|
|
// }
|
|
//
|
|
// Health checks verify:
|
|
// - Server is running (runner state check)
|
|
// - Port is bound and accepting connections
|
|
// - No fatal errors in server operation
|
|
// - TCP connection can be established to bind address
|
|
//
|
|
// Monitor provides:
|
|
// - Health check status and last error
|
|
// - Server configuration and runtime information
|
|
// - Uptime and running state
|
|
// - Custom metrics from monitoring configuration
|
|
//
|
|
// # Port Management
|
|
//
|
|
// The package includes port conflict detection and resolution:
|
|
//
|
|
// // Check if port is available
|
|
// err := httpserver.PortNotUse(ctx, "127.0.0.1:8080")
|
|
// if err == nil {
|
|
// // Port is available
|
|
// }
|
|
//
|
|
// // Check if port is in use
|
|
// err = httpserver.PortInUse(ctx, "127.0.0.1:8080")
|
|
// if err == nil {
|
|
// // Port is in use
|
|
// }
|
|
//
|
|
// Automatic Port Conflict Handling:
|
|
//
|
|
// Servers automatically check for port conflicts before binding:
|
|
// - Retries up to 5 times with delays
|
|
// - Returns ErrorPortUse if port remains unavailable
|
|
// - Configurable retry count via RunIfPortInUse
|
|
//
|
|
// # Error Handling
|
|
//
|
|
// The package defines typed errors with diagnostic codes:
|
|
//
|
|
// Error Code | Description
|
|
// -----------------------|------------------------------------------
|
|
// ErrorParamEmpty | Required parameter missing
|
|
// ErrorInvalidInstance | Invalid server instance
|
|
// ErrorHTTP2Configure | HTTP/2 configuration failed
|
|
// ErrorServerValidate | Configuration validation failed
|
|
// ErrorServerStart | Server failed to start or listen
|
|
// ErrorInvalidAddress | Bind address format invalid
|
|
// ErrorPortUse | Port is already in use
|
|
//
|
|
// Error checking:
|
|
//
|
|
// if err := srv.Start(ctx); err != nil {
|
|
// var liberr errors.Error
|
|
// if errors.As(err, &liberr) {
|
|
// switch liberr.Code() {
|
|
// case httpserver.ErrorPortUse:
|
|
// log.Println("Port already in use")
|
|
// case httpserver.ErrorServerValidate:
|
|
// log.Println("Invalid configuration")
|
|
// default:
|
|
// log.Printf("Server error: %v", err)
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// # Performance Characteristics
|
|
//
|
|
// Server Operations:
|
|
//
|
|
// Operation | Time | Memory | Notes
|
|
// ------------------------|--------------|-----------|------------------------
|
|
// Config Validation | ~100ns | O(1) | Field validation only
|
|
// Server Creation | <1ms | ~5KB | Includes initialization
|
|
// Start Server | 1-5ms | ~10KB | Port binding overhead
|
|
// Stop Server (graceful) | <5s | O(1) | Default timeout
|
|
// Handler Execution | Variable | Variable | Depends on handler
|
|
// Info Methods | <100ns | O(1) | Atomic reads
|
|
// Configuration Update | <1ms | O(1) | Validation + atomic swap
|
|
//
|
|
// Throughput:
|
|
// - HTTP Requests: Limited by Go's http.Server (~50k+ req/s typical)
|
|
// - HTTPS/TLS: ~20-30k req/s depending on cipher suite and hardware
|
|
// - Overhead: Minimal (<1% vs standard http.Server)
|
|
//
|
|
// Memory Usage:
|
|
// - Single Server: ~10-15KB baseline + handler memory
|
|
// - With Monitoring: +5KB per server
|
|
// - Pool Overhead: ~1KB per server in pool
|
|
//
|
|
// Scalability:
|
|
// - Supports hundreds of server instances per process
|
|
// - Linear memory growth with server count
|
|
// - No global locks on request path
|
|
//
|
|
// # Use Cases
|
|
//
|
|
// ## Microservices Architecture
|
|
//
|
|
// Run multiple API versions simultaneously:
|
|
//
|
|
// // API v1 on port 8080
|
|
// cfgV1 := httpserver.Config{
|
|
// Name: "api-v1",
|
|
// Listen: "0.0.0.0:8080",
|
|
// Expose: "http://api.example.com/v1",
|
|
// HandlerKey: "v1",
|
|
// }
|
|
//
|
|
// // API v2 on port 8081
|
|
// cfgV2 := httpserver.Config{
|
|
// Name: "api-v2",
|
|
// Listen: "0.0.0.0:8081",
|
|
// Expose: "http://api.example.com/v2",
|
|
// HandlerKey: "v2",
|
|
// }
|
|
//
|
|
// ## Multi-Tenant Systems
|
|
//
|
|
// Dedicated server per tenant with isolated configuration:
|
|
//
|
|
// for _, tenant := range tenants {
|
|
// cfg := httpserver.Config{
|
|
// Name: tenant.ID,
|
|
// Listen: fmt.Sprintf("0.0.0.0:%d", tenant.Port),
|
|
// Expose: tenant.Domain,
|
|
// TLS: tenant.TLSConfig,
|
|
// }
|
|
// srv, _ := httpserver.New(cfg, nil)
|
|
// srv.Start(ctx)
|
|
// }
|
|
//
|
|
// ## Development and Testing
|
|
//
|
|
// Dynamic server creation for integration tests:
|
|
//
|
|
// func TestAPI(t *testing.T) {
|
|
// port := getFreePort()
|
|
// cfg := httpserver.Config{
|
|
// Name: "test-server",
|
|
// Listen: fmt.Sprintf("127.0.0.1:%d", port),
|
|
// Expose: fmt.Sprintf("http://localhost:%d", port),
|
|
// }
|
|
// cfg.RegisterHandlerFunc(testHandler)
|
|
// srv, _ := httpserver.New(cfg, nil)
|
|
// srv.Start(context.Background())
|
|
// defer srv.Stop(context.Background())
|
|
// // Run tests...
|
|
// }
|
|
//
|
|
// ## API Gateway
|
|
//
|
|
// Route traffic to multiple backend servers:
|
|
//
|
|
// pool := pool.New(nil, gatewayHandler)
|
|
// for _, backend := range backends {
|
|
// cfg := httpserver.Config{
|
|
// Name: backend.Name,
|
|
// Listen: backend.Address,
|
|
// Expose: backend.URL,
|
|
// }
|
|
// pool.StoreNew(cfg, nil)
|
|
// }
|
|
// pool.Start(ctx)
|
|
//
|
|
// ## Production Deployments
|
|
//
|
|
// Graceful shutdown during rolling updates:
|
|
//
|
|
// // Handle SIGTERM for graceful shutdown
|
|
// sigChan := make(chan os.Signal, 1)
|
|
// signal.Notify(sigChan, syscall.SIGTERM)
|
|
// go func() {
|
|
// <-sigChan
|
|
// ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
// defer cancel()
|
|
// if err := srv.Stop(ctx); err != nil {
|
|
// log.Printf("Shutdown error: %v", err)
|
|
// }
|
|
// }()
|
|
//
|
|
// # Limitations
|
|
//
|
|
// 1. Handler Replacement During Operation: Handlers can be replaced while the server
|
|
// is running, but active requests continue using the previous handler. New requests
|
|
// use the updated handler. This may cause inconsistent behavior during handler updates.
|
|
//
|
|
// 2. TLS Certificate Rotation: Updating TLS certificates requires server restart.
|
|
// The SetConfig method does not apply TLS changes to running servers.
|
|
//
|
|
// 3. Port Binding Limitations: Cannot bind to privileged ports (<1024) without
|
|
// appropriate system permissions (CAP_NET_BIND_SERVICE on Linux or root access).
|
|
//
|
|
// 4. Listen Address Changes: Changing the Listen address via SetConfig requires
|
|
// a server restart to take effect. The new address is not applied to running servers.
|
|
//
|
|
// 5. HTTP/2 Configuration: HTTP/2 settings cannot be changed after server creation
|
|
// without recreating the server instance.
|
|
//
|
|
// 6. Concurrent Stop Calls: Multiple concurrent Stop calls may result in redundant
|
|
// shutdown attempts. Use external synchronization if multiple goroutines may call Stop.
|
|
//
|
|
// 7. Context Cancellation: Server operations respect context cancellation, but
|
|
// forcefully cancelled contexts (e.g., exceeded deadline during graceful shutdown)
|
|
// may result in abrupt connection termination.
|
|
//
|
|
// 8. Monitoring Overhead: Each server maintains monitoring state. For deployments
|
|
// with hundreds of servers, consider disabling monitoring for non-critical instances.
|
|
//
|
|
// # Best Practices
|
|
//
|
|
// DO:
|
|
// - Always validate configuration before creating servers
|
|
// - Use context.WithTimeout for Stop operations to prevent hanging
|
|
// - Register handlers before calling New() when possible
|
|
// - Use defer srv.Stop(ctx) to ensure cleanup
|
|
// - Check IsRunning() before calling Stop to avoid errors
|
|
// - Set appropriate timeouts (ReadTimeout, WriteTimeout, IdleTimeout)
|
|
// - Use the pool subpackage for managing multiple servers
|
|
// - Monitor server health in production deployments
|
|
// - Use unique server names for debugging and monitoring
|
|
//
|
|
// DON'T:
|
|
// - Don't create servers without validating configuration
|
|
// - Don't ignore errors from Start, Stop, or SetConfig
|
|
// - Don't assume port availability without checking
|
|
// - Don't call Stop without context timeout
|
|
// - Don't modify Config after passing to New() (use Clone first)
|
|
// - Don't rely on handler updates to active connections
|
|
// - Don't bind to 0.0.0.0 without considering security implications
|
|
// - Don't start servers in goroutines without proper error handling
|
|
//
|
|
// # Integration with Standard Library
|
|
//
|
|
// The package integrates seamlessly with Go's standard library:
|
|
//
|
|
// Standard Library | Integration Point
|
|
// -------------------------|------------------------------------------
|
|
// net/http.Server | Wrapped and managed by this package
|
|
// net/http.Handler | Compatible with all standard handlers
|
|
// context.Context | Used throughout for cancellation
|
|
// net.Listener | Managed internally for binding
|
|
// crypto/tls | TLS configuration via certificates package
|
|
//
|
|
// # Related Packages
|
|
//
|
|
// This package works with other golib packages:
|
|
//
|
|
// - github.com/nabbar/golib/httpserver/pool: Multi-server orchestration
|
|
// - github.com/nabbar/golib/httpserver/types: Shared type definitions
|
|
// - github.com/nabbar/golib/certificates: TLS/SSL certificate management
|
|
// - github.com/nabbar/golib/monitor: Health checking and metrics
|
|
// - github.com/nabbar/golib/logger: Structured logging integration
|
|
// - github.com/nabbar/golib/runner: Lifecycle management primitives
|
|
// - github.com/nabbar/golib/context: Typed context storage
|
|
//
|
|
// External Dependencies:
|
|
//
|
|
// - github.com/go-playground/validator/v10: Configuration validation
|
|
// - golang.org/x/net/http2: HTTP/2 support
|
|
//
|
|
// # Testing
|
|
//
|
|
// The package includes comprehensive testing using Ginkgo v2 and Gomega:
|
|
//
|
|
// - Configuration validation tests
|
|
// - Server lifecycle tests (start, stop, restart)
|
|
// - Handler management tests
|
|
// - Monitoring integration tests
|
|
// - Concurrency and race detection tests
|
|
// - Integration tests with actual HTTP servers
|
|
//
|
|
// Run tests:
|
|
//
|
|
// go test -v ./...
|
|
// go test -race -v ./...
|
|
// go test -cover -v ./...
|
|
//
|
|
// For detailed testing documentation, see TESTING.md in the package directory.
|
|
//
|
|
// # Examples
|
|
//
|
|
// See example_test.go for comprehensive usage examples covering:
|
|
// - Basic HTTP server creation and lifecycle
|
|
// - HTTPS server with TLS configuration
|
|
// - Multiple handlers with handler keys
|
|
// - Server pool management
|
|
// - Dynamic configuration updates
|
|
// - Graceful shutdown patterns
|
|
// - Monitoring integration
|
|
// - Error handling strategies
|
|
package httpserver
|