types

package
v1.19.2 Latest Latest
Warning

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

Go to latest
Published: Feb 4, 2026 License: MIT Imports: 2 Imported by: 0

README

HTTPServer Types

License Go Version Coverage

Core type definitions and constants for HTTP server implementations providing foundational types for handler registration, server field identification, and timeout management.


Table of Contents


Overview

The httpserver/types package provides foundational type definitions and constants for HTTP server implementations. It serves as the shared type system for server configuration, handler registration, field identification, and timeout management across the httpserver ecosystem.

Why a Separate Types Package?

Separating types into their own package provides several architectural benefits:

Benefits of Dedicated Types:

  • No Circular Dependencies: Higher-level packages (httpserver, pool) can import types without dependency cycles
  • Shared Vocabulary: Consistent type definitions across all HTTP server components
  • Minimal Import Footprint: Packages importing types don't pull in heavy dependencies
  • Interface Stability: Type definitions remain stable even as implementations evolve
  • Clear Contracts: FuncHandler and FieldType define explicit contracts for server operations
  • Type Safety: Compile-time guarantees prevent invalid field specifications and handler types

Internally, the types package uses only standard library primitives (net/http, time), ensuring zero external dependencies. This makes it suitable as a foundation layer that other packages can safely depend on without transitive dependency concerns.

Design Philosophy
  1. Minimal Dependencies: Depend only on standard library to serve as stable foundation for higher-level packages.
  2. Type Safety First: Use custom types (FieldType) to provide compile-time safety and prevent invalid operations.
  3. Fail-Safe Defaults: Provide safe fallbacks (BadHandler) that fail visibly rather than silently.
  4. Constants Over Magic Values: Use named constants for all configuration values to improve code readability.
  5. Zero Allocation Types: Design types for minimal runtime overhead (empty structs, uint8 enums).
  6. Interface Compliance: Ensure types properly implement standard interfaces (http.Handler).
Key Features
  • Field Type System: FieldType enumeration enables type-safe server filtering by name, bind address, or expose URL.
  • Handler Registration: FuncHandler defines the contract for dynamic handler registration.
  • Fallback Handling: BadHandler provides a safe default when no valid handler is configured.
  • Timeout Management: Pre-defined timeout constants standardize server lifecycle operations.
  • Zero Dependencies: Only depends on standard library net/http and time.
  • Minimal Overhead: Types designed for zero or minimal runtime allocation.

Architecture

Component Diagram
┌────────────────────────────────────────────────────────────┐
│                     httpserver/types                       │
├────────────────────────────────────────────────────────────┤
│                                                            │
│  ┌──────────────────┐           ┌─────────────────────┐    │
│  │   Field Types    │           │   Handler Types     │    │
│  │  (Enumeration)   │           │   (Interfaces)      │    │
│  └──────┬───────────┘           └──────────┬──────────┘    │
│         │                                  │               │
│         ▼                                  ▼               │
│  ┌──────────────────┐           ┌─────────────────────┐    │
│  │ FieldType (uint8)│           │ FuncHandler (func)  │    │
│  ├──────────────────┤           ├─────────────────────┤    │
│  │ FieldName = 0    │           │ Returns map[string] │    │
│  │ FieldBind = 1    │           │   http.Handler      │    │
│  │ FieldExpose = 2  │           │                     │    │
│  └──────────────────┘           └─────────────────────┘    │
│                                                            │
│  ┌──────────────────┐           ┌─────────────────────┐    │
│  │    Constants     │           │   Default Handler   │    │
│  ├──────────────────┤           ├─────────────────────┤    │
│  │ HandlerDefault   │           │ BadHandler struct{} │    │
│  │ BadHandlerName   │           │ NewBadHandler()     │    │
│  │ TimeoutWaiting*  │           │ ServeHTTP() → 500   │    │
│  └──────────────────┘           └─────────────────────┘    │
│                                                            │
└────────────────────────────────────────────────────────────┘
                          │
                          ▼
         ┌────────────────────────────────────┐
         │   Consuming Packages               │
         ├────────────────────────────────────┤
         │ httpserver       (server impl)     │
         │ httpserver/pool  (server registry) │
         │ Application code (configuration)   │
         └────────────────────────────────────┘
Data Flow
  1. Type Definition:

    • Constants are compiled at build time (zero runtime cost).
    • FieldType values are uint8 enums (1 byte each).
    • BadHandler is an empty struct (zero bytes).
  2. Handler Registration:

    • FuncHandler is invoked to retrieve handler map.
    • Map keys use HandlerDefault constant or custom strings.
    • Handlers are registered in server configuration.
  3. Field Filtering:

    • Server pool queries use FieldType for type-safe filtering.
    • Switch statements or map keys use enum values.
    • Compile-time type checking prevents invalid fields.
Limitations

This package is intentionally minimal with the following design constraints:

  1. No Dynamic Field Types: FieldType is a closed enumeration (0, 1, 2). Adding new field types requires modifying this package and recompiling consuming packages.

  2. No Handler Lifecycle Management: BadHandler does not implement graceful shutdown, resource cleanup, or lifecycle hooks. It's a stateless fallback.

  3. Fixed Timeout Values: Timeout constants (TimeoutWaitingStop, TimeoutWaitingPortFreeing) are compile-time constants and cannot be configured at runtime.

  4. No Validation: The package does not validate handler maps returned by FuncHandler. Validation is the responsibility of consuming packages.

  5. Single Error Status: BadHandler always returns HTTP 500 Internal Server Error. Custom error codes require implementing a custom http.Handler.

  6. No State Management: Types are stateless primitives. State management (server instances, handler routing) is handled by consuming packages.


Performance

Benchmarks

Based on type characteristics (Go 1.25, standard library primitives):

Operation Runtime Cost Memory Cost
FieldType Comparison 0 ns 0 bytes
Constant Access 0 ns 0 bytes
BadHandler Creation <10 ns 0 bytes (empty struct)
BadHandler.ServeHTTP <100 ns 0 allocations
FuncHandler Invocation Depends on implementation Depends on map size

Note: FieldType and constants are compile-time values with zero runtime overhead.

Memory Usage
  • Base Overhead: Zero (all types are primitives or empty structs).
  • FieldType: 1 byte per variable (uint8).
  • BadHandler: 0 bytes (empty struct, allocated on stack).
  • Constants: Compiled into binary, no runtime memory allocation.
  • Optimization: Types designed for zero-allocation scenarios where possible.
Scalability
  • Type Safety: Compile-time checks scale to any codebase size.
  • Constant Propagation: Compiler optimizes constant usage at compile time.
  • Zero Contention: No shared mutable state, safe for unlimited concurrent use.
  • Handler Maps: Scalability depends on FuncHandler implementation (not managed by this package).

Use Cases

1. Server Pool Management

Filter servers in a pool by specific attributes:

// Find all servers listening on a specific address
servers := pool.FilterByField(types.FieldBind, ":8080")
2. Multi-Handler Server Configuration

Register multiple handlers for different routes or purposes:

cfg.HandlerFunc = func() map[string]http.Handler {
    return map[string]http.Handler{
        types.HandlerDefault: webHandler,
        "api":                apiHandler,
        "metrics":            metricsHandler,
    }
}
3. Graceful Shutdown

Use standard timeout for server shutdown:

shutdownCtx, cancel := context.WithTimeout(
    context.Background(),
    types.TimeoutWaitingStop,
)
defer cancel()
server.Shutdown(shutdownCtx)
4. Safe Default Handler

Provide fallback when handler registration fails:

handler := getConfiguredHandler()
if handler == nil {
    handler = types.NewBadHandler()
}

Quick Start

Installation
go get github.com/nabbar/golib/httpserver/types
Basic Field Type Usage
package main

import (
    "fmt"
    "github.com/nabbar/golib/httpserver/types"
)

func main() {
    // Use FieldType for server filtering
    filterByField := func(field types.FieldType, value string) {
        switch field {
        case types.FieldName:
            fmt.Println("Filtering by server name:", value)
        case types.FieldBind:
            fmt.Println("Filtering by bind address:", value)
        case types.FieldExpose:
            fmt.Println("Filtering by expose URL:", value)
        }
    }
    
    filterByField(types.FieldBind, ":8080")
}
Handler Registration
package main

import (
    "net/http"
    "github.com/nabbar/golib/httpserver/types"
)

func main() {
    // Define handler registration function
    var handlerFunc types.FuncHandler
    
    handlerFunc = func() map[string]http.Handler {
        return map[string]http.Handler{
            types.HandlerDefault: http.NotFoundHandler(),
            "api":                myAPIHandler,
            "admin":              myAdminHandler,
        }
    }
    
    // Use in server configuration
    handlers := handlerFunc()
    server.RegisterHandlers(handlers)
}
Using Timeout Constants
package main

import (
    "context"
    "time"
    "github.com/nabbar/golib/httpserver/types"
)

func main() {
    // Use predefined timeout for server shutdown
    ctx, cancel := context.WithTimeout(
        context.Background(),
        types.TimeoutWaitingStop,
    )
    defer cancel()
    
    if err := server.Shutdown(ctx); err != nil {
        log.Printf("Shutdown error: %v", err)
    }
}

Best Practices

Testing

The package includes a comprehensive test suite with 100.0% code coverage and 32 test specifications using BDD methodology (Ginkgo v2 + Gomega).

Key test coverage:

  • ✅ All type definitions and constants
  • ✅ Field type enumeration and usage
  • ✅ Handler creation and ServeHTTP behavior
  • ✅ Constant values verification
  • ✅ Interface compliance

For detailed test documentation, see TESTING.md.

✅ DO

Use FieldType constants:

// ✅ GOOD: Type-safe field filtering
switch filterField {
case types.FieldName:
    // Filter by name
case types.FieldBind:
    // Filter by bind address
}

Use HandlerDefault:

// ✅ GOOD: Standard handler registration
handlers := map[string]http.Handler{
    types.HandlerDefault: myHandler,
}

Use timeout constants:

// ✅ GOOD: Consistent timeout management
ctx, cancel := context.WithTimeout(ctx, types.TimeoutWaitingStop)
defer cancel()
❌ DON'T

Don't cast arbitrary integers to FieldType:

// ❌ BAD: Type-unsafe field creation
field := types.FieldType(99)  // No validation

// ✅ GOOD: Use defined constants
field := types.FieldName

Don't rely on BadHandler for production:

// ❌ BAD: Using error handler for normal traffic
handler := types.NewBadHandler()
server.SetHandler(handler)  // Always returns 500!

// ✅ GOOD: Use as fallback only
handler := configuredHandler
if handler == nil {
    handler = types.NewBadHandler()
}

Don't modify timeout constants:

// ❌ BAD: Can't modify package constants
types.TimeoutWaitingStop = 10 * time.Second  // Won't compile

// ✅ GOOD: Define your own if needed
const myTimeout = 10 * time.Second

API Reference

Field Types
// FieldType identifies server fields for filtering and listing operations
type FieldType uint8

const (
    FieldName   FieldType = iota  // Server name field
    FieldBind                      // Bind address field (Listen)
    FieldExpose                    // Expose URL field
)
Handler Types
// FuncHandler is the function signature for handler registration
type FuncHandler func() map[string]http.Handler

// NewBadHandler creates a default error handler
func NewBadHandler() http.Handler

// BadHandler returns HTTP 500 for all requests
type BadHandler struct{}
func (o BadHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request)
Constants
const (
    // HandlerDefault is the default handler registration key
    HandlerDefault = "default"
    
    // TimeoutWaitingPortFreeing is the port availability check timeout
    TimeoutWaitingPortFreeing = 250 * time.Microsecond
    
    // TimeoutWaitingStop is the graceful server shutdown timeout
    TimeoutWaitingStop = 5 * time.Second
    
    // BadHandlerName is the identifier for BadHandler
    BadHandlerName = "no handler"
)

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Code Quality

    • Follow Go best practices and idioms
    • Maintain or improve code coverage (target: >80%)
    • Pass all tests including race detector
    • Use gofmt and golint
  2. AI Usage Policy

    • AI must NEVER be used to generate package code or core functionality
    • AI assistance is limited to:
      • Testing (writing and improving tests)
      • Debugging (troubleshooting and bug resolution)
      • Documentation (comments, README, TESTING.md)
    • All AI-assisted work must be reviewed and validated by humans
  3. Testing

    • Add tests for new features
    • Use Ginkgo v2 / Gomega for test framework
    • Ensure zero race conditions with go test -race
  4. Documentation

    • Update GoDoc comments for public APIs
    • Add examples for new features
    • Update README.md and TESTING.md if needed
  5. Pull Request Process

    • Fork the repository
    • Create a feature branch
    • Write clear commit messages
    • Ensure all tests pass
    • Update documentation
    • Submit PR with description of changes

Improvements & Security

Current Status

The package is production-ready with no urgent improvements or security vulnerabilities identified.

Code Quality Metrics
  • 100.0% test coverage (target: >80%)
  • Zero race conditions detected with -race flag
  • Thread-safe - all types are immutable or stateless
  • Minimal dependencies - only standard library
  • Type-safe - compile-time safety for field types
Future Enhancements (Non-urgent)

The following enhancements could be considered for future versions:

  1. Extended Field Types: Additional server properties for filtering (status, protocol, etc.)
  2. Handler Validation: Optional validation interface for FuncHandler implementations
  3. Custom Error Codes: BadHandler with configurable HTTP status codes
  4. Handler Middleware: Built-in middleware support for handler chains

These are optional improvements and not required for production use. The current implementation is stable and minimal by design.


Resources

Package Documentation
  • GoDoc - Complete API reference with function signatures, method descriptions, and runnable examples. Essential for understanding the public interface and usage patterns.

  • doc.go - In-depth package documentation including design philosophy, type definitions, usage patterns, and limitations. Provides detailed explanations of each type and constant.

  • TESTING.md - Comprehensive test suite documentation covering test architecture, BDD methodology with Ginkgo v2, 100% coverage analysis, and guidelines for writing new tests.

External References
  • net/http Package - Standard library HTTP package. The types package extends net/http with additional type definitions for server management.

  • Effective Go - Official Go programming guide covering best practices for type definitions, constants, and interface usage.


AI Transparency

In compliance with EU AI Act Article 50.4: AI assistance was used for testing, documentation, and bug resolution under human supervision. All core functionality is human-designed and validated.


License

MIT License - See LICENSE file for details.

Copyright (c) 2025 Nicolas JUHEL


Maintained by: Nicolas JUHEL
Package: github.com/nabbar/golib/httpserver/types
Version: See releases for versioning

Documentation

Overview

Package types provides core type definitions and constants for HTTP server implementations.

Overview

This package defines foundational types, constants, and utilities used across the httpserver ecosystem. It serves as a shared vocabulary for server configuration, handler registration, and field identification in server management operations.

The package provides:

  • Field type enumeration for server property filtering
  • Handler registration function signatures
  • Fallback error handlers for misconfigured servers
  • Timeout constants for server lifecycle management

Design Philosophy

The types package follows these design principles:

1. Minimal Dependencies: The package depends only on the standard library, making it suitable as a foundation for higher-level packages without circular dependencies.

2. Type Safety: Custom types like FieldType provide compile-time safety for server filtering operations, preventing invalid field specifications.

3. Fail-Safe Defaults: The BadHandler provides a safe fallback that always returns HTTP 500, ensuring misconfigured servers fail visibly rather than silently.

4. Constants Over Magic Values: Named constants like TimeoutWaitingStop and HandlerDefault improve code readability and maintainability.

Key Features

Field Type System: FieldType enumeration enables type-safe server filtering by name, bind address, or expose URL. This is primarily used by the pool package for server management.

Handler Registration: FuncHandler defines the contract for dynamic handler registration, allowing multiple named handlers per server instance.

Fallback Handling: BadHandler provides a safe default when no valid handler is configured, preventing nil pointer panics and providing clear error signals.

Timeout Management: Pre-defined timeout constants standardize server lifecycle operations like graceful shutdown and port availability checks.

Architecture

The package structure is intentionally flat, providing building blocks for higher-level abstractions:

┌────────────────────────────────────────────────────┐
│                  httpserver/types                  │
├────────────────────────────────────────────────────┤
│                                                    │
│  ┌──────────────────┐        ┌──────────────────┐  │
│  │   Field Types    │        │   Handler Types  │  │
│  ├──────────────────┤        ├──────────────────┤  │
│  │ FieldType        │        │ FuncHandler      │  │
│  │  - FieldName     │        │ BadHandler       │  │
│  │  - FieldBind     │        │ NewBadHandler()  │  │
│  │  - FieldExpose   │        │                  │  │
│  └──────────────────┘        └──────────────────┘  │
│                                                    │
│  ┌──────────────────┐        ┌──────────────────┐  │
│  │    Constants     │        │   Handler Keys   │  │
│  ├──────────────────┤        ├──────────────────┤  │
│  │ TimeoutWaiting   │        │ HandlerDefault   │  │
│  │  PortFreeing     │        │ BadHandlerName   │  │
│  │ TimeoutWaiting   │        │                  │  │
│  │  Stop            │        │                  │  │
│  └──────────────────┘        └──────────────────┘  │
│                                                    │
└────────────────────────────────────────────────────┘
                          │
                          ▼
         Used by httpserver, httpserver/pool,
         and other HTTP server components

Usage Patterns

## Field Type Filtering

FieldType enables type-safe filtering of servers by specific attributes:

switch filterField {
case types.FieldName:
    // Filter by server name
case types.FieldBind:
    // Filter by bind address
case types.FieldExpose:
    // Filter by expose URL
}

## Handler Registration

FuncHandler defines how handlers are registered with servers:

handlerFunc := func() map[string]http.Handler {
    return map[string]http.Handler{
        types.HandlerDefault: myDefaultHandler,
        "api":                myAPIHandler,
        "admin":              myAdminHandler,
    }
}

## Fallback Handler

BadHandler provides safe error handling for misconfigured servers:

handler := types.NewBadHandler()
// Returns HTTP 500 for all requests

## Timeout Constants

Standard timeouts for server lifecycle operations:

ctx, cancel := context.WithTimeout(ctx, types.TimeoutWaitingStop)
defer cancel()
server.Shutdown(ctx)

Field Types

FieldType is an enumeration for identifying server properties in filtering and listing operations:

FieldName:   Server name identifier
FieldBind:   Server listen address (e.g., ":8080", "127.0.0.1:9000")
FieldExpose: Server public expose URL (e.g., "https://example.com")

These types are primarily used by the pool package to filter and retrieve servers based on specific criteria.

Handler Types

## FuncHandler

FuncHandler defines the signature for handler registration functions. It returns a map of handler identifiers to http.Handler instances:

Key patterns:
  - "" or "default": Default handler for unmatched routes
  - "api": API-specific handler
  - "admin": Administrative interface handler
  - Custom keys: Application-specific handler identifiers

## BadHandler

BadHandler is a fallback http.Handler that returns HTTP 500 Internal Server Error for all requests. It's used when:

  • No handler is registered for a server
  • Handler registration fails
  • Configuration errors prevent proper handler setup

The handler serves as a visible failure indicator rather than panicking or silently ignoring requests.

Constants

## Timeout Constants

TimeoutWaitingPortFreeing (250µs):

  • Duration for polling port availability before binding
  • Used in port conflict detection and retry logic
  • Short duration suitable for tight polling loops

TimeoutWaitingStop (5s):

  • Default timeout for graceful server shutdown
  • Allows ongoing requests to complete before forced termination
  • Balances graceful shutdown with reasonable wait times

## Handler Identifier Constants

HandlerDefault ("default"):

  • Standard key for default handler registration
  • Used when no specific handler key is configured
  • Fallback handler for unmatched routes

BadHandlerName ("no handler"):

  • Identifier string for BadHandler instances
  • Used in logging and monitoring
  • Indicates misconfigured or missing handler

Integration with httpserver Ecosystem

This package integrates with:

httpserver:      Core server implementation uses these types
httpserver/pool: Server pooling uses FieldType for filtering
httpserver/config: Configuration uses timeout constants

Performance Considerations

Type Overhead:

  • FieldType is a uint8 (1 byte), minimal memory overhead
  • Handler maps are created on-demand, not stored statically
  • BadHandler is stateless, safe to create multiple instances

Constant Access:

  • All constants are compile-time values
  • Zero runtime overhead for constant access
  • No initialization required

Handler Performance:

  • BadHandler.ServeHTTP is a trivial function (single line)
  • No allocations, no blocking operations
  • Suitable for high-frequency error scenarios

Limitations

1. No Dynamic Field Types: FieldType is a closed enumeration. Adding new field types requires modifying this package.

2. No Handler Lifecycle Management: BadHandler does not implement graceful shutdown or resource cleanup. It's stateless by design.

3. Fixed Timeout Values: Timeout constants are not configurable at runtime. Applications needing custom timeouts should define their own.

4. No Validation: The package does not validate handler maps returned by FuncHandler. Validation is the responsibility of consuming packages.

5. Single Error Status: BadHandler always returns 500. It does not support custom error codes or messages.

Use Cases

## Server Pool Management

Filter servers in a pool by specific attributes:

// Find all servers listening on a specific address
servers := pool.FilterByField(types.FieldBind, ":8080")

## Multi-Handler Server Configuration

Register multiple handlers for different routes or purposes:

cfg.HandlerFunc = func() map[string]http.Handler {
    return map[string]http.Handler{
        types.HandlerDefault: webHandler,
        "api":                apiHandler,
        "metrics":            metricsHandler,
    }
}

## Graceful Shutdown

Use standard timeout for server shutdown:

shutdownCtx, cancel := context.WithTimeout(
    context.Background(),
    types.TimeoutWaitingStop,
)
defer cancel()
server.Shutdown(shutdownCtx)

## Safe Default Handler

Provide fallback when handler registration fails:

handler := getConfiguredHandler()
if handler == nil {
    handler = types.NewBadHandler()
}

Thread Safety

All types in this package are safe for concurrent use:

  • FieldType is a simple enumeration (immutable)
  • Constants are immutable by definition
  • BadHandler is stateless and safe for concurrent ServeHTTP calls
  • FuncHandler signature does not enforce thread safety; implementations must ensure their own thread safety if called concurrently

Error Handling

The package provides minimal error handling as it defines types rather than implementing complex logic:

  • BadHandler signals errors via HTTP 500 status code
  • No errors are returned by package functions
  • Invalid FieldType values are not validated at runtime

Consumer packages are responsible for validating inputs and handling errors appropriately.

Best Practices

DO:

  • Use FieldType constants for server filtering to avoid typos
  • Use HandlerDefault for primary handler registration
  • Use NewBadHandler() as a safe fallback for missing handlers
  • Use timeout constants for consistent server lifecycle management
  • Document custom handler keys in application code

DON'T:

  • Don't cast arbitrary integers to FieldType
  • Don't rely on BadHandler for production traffic
  • Don't modify timeout constants (they're package-level)
  • Don't assume FuncHandler implementations are thread-safe
  • Don't use BadHandler for intentional error responses

Testing

The package includes comprehensive testing:

  • Field type enumeration and uniqueness
  • Constant value verification
  • BadHandler HTTP response validation
  • FuncHandler signature compliance
  • Integration with http.Handler interface

See fields_test.go and handler_test.go for detailed test specifications.

  • net/http: Standard library HTTP server interfaces
  • github.com/nabbar/golib/httpserver: HTTP server implementation
  • github.com/nabbar/golib/httpserver/pool: Server pool management

For usage examples, see example_test.go in this package.

Example (BadHandlerMultipleRequests)

Example_badHandlerMultipleRequests demonstrates BadHandler with multiple requests. Shows that BadHandler consistently returns 500 for all requests.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	handler := types.NewBadHandler()

	methods := []string{http.MethodGet, http.MethodPost, http.MethodPut}

	for _, method := range methods {
		req := httptest.NewRequest(method, "/test", nil)
		w := httptest.NewRecorder()
		handler.ServeHTTP(w, req)
		fmt.Printf("%s: %d\n", method, w.Code)
	}
}
Output:

GET: 500
POST: 500
PUT: 500
Example (BadHandlerName)

Example_badHandlerName demonstrates the BadHandlerName constant. This shows the identifier used for BadHandler instances.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	handlerName := types.BadHandlerName

	fmt.Printf("Bad handler identifier: %s\n", handlerName)
}
Output:

Bad handler identifier: no handler
Example (Complete)

Example_complete demonstrates combining all types package features. This is the most complex example showing realistic integration.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	type srvCfg struct {
		name    string
		bind    string
		expose  string
		handler http.Handler
	}

	createServerConfig := func(name, bind, expose string, handlerFunc types.FuncHandler) srvCfg {
		handlers := handlerFunc()
		handler := handlers[types.HandlerDefault]

		if handler == nil {
			handler = types.NewBadHandler()
		}

		return srvCfg{
			name:    name,
			bind:    bind,
			expose:  expose,
			handler: handler,
		}
	}

	handlerFunc := func() map[string]http.Handler {
		return map[string]http.Handler{
			types.HandlerDefault: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusOK)
			}),
		}
	}

	cfg := createServerConfig("api-server", ":8080", "https://api.example.com", handlerFunc)

	fmt.Printf("Server: %s\n", cfg.name)
	fmt.Printf("Bind: %s\n", cfg.bind)
	fmt.Printf("Expose: %s\n", cfg.expose)

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	w := httptest.NewRecorder()
	cfg.handler.ServeHTTP(w, req)

	fmt.Printf("Handler status: %d\n", w.Code)
}
Output:

Server: api-server
Bind: :8080
Expose: https://api.example.com
Handler status: 200
Example (FieldTypeComparison)

Example_fieldTypeComparison demonstrates comparing FieldType values. This is useful for validation and conditional logic.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	field1 := types.FieldName
	field2 := types.FieldName
	field3 := types.FieldBind

	fmt.Printf("field1 == field2: %t\n", field1 == field2)
	fmt.Printf("field1 == field3: %t\n", field1 == field3)
}
Output:

field1 == field2: true
field1 == field3: false
Example (FieldTypeMap)

Example_fieldTypeMap demonstrates using FieldType as map keys. This pattern is useful for storing field-specific configurations.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	fieldNames := map[types.FieldType]string{
		types.FieldName:   "server-name",
		types.FieldBind:   "bind-address",
		types.FieldExpose: "expose-url",
	}

	fields := []types.FieldType{types.FieldName, types.FieldBind, types.FieldExpose}
	for _, field := range fields {
		fmt.Printf("Field %d: %s\n", field, fieldNames[field])
	}
}
Output:

Field 0: server-name
Field 1: bind-address
Field 2: expose-url
Example (FieldTypeSwitch)

Example_fieldTypeSwitch demonstrates using FieldType in switch statements. This shows how to handle different field types in filtering operations.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	fields := []types.FieldType{
		types.FieldName,
		types.FieldBind,
		types.FieldExpose,
	}

	for _, field := range fields {
		switch field {
		case types.FieldName:
			fmt.Println("Filtering by name")
		case types.FieldBind:
			fmt.Println("Filtering by bind address")
		case types.FieldExpose:
			fmt.Println("Filtering by expose URL")
		}
	}
}
Output:

Filtering by name
Filtering by bind address
Filtering by expose URL
Example (FuncHandler)

Example_funcHandler demonstrates implementing FuncHandler. This is a simple example of handler registration function.

package main

import (
	"fmt"
	"net/http"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	var handlerFunc types.FuncHandler

	handlerFunc = func() map[string]http.Handler {
		return map[string]http.Handler{
			types.HandlerDefault: http.NotFoundHandler(),
		}
	}

	handlers := handlerFunc()
	fmt.Printf("Handlers returned: %d\n", len(handlers))
}
Output:

Handlers returned: 1
Example (FuncHandlerMultiple)

Example_funcHandlerMultiple demonstrates multiple handler registration. This shows how to register multiple named handlers.

package main

import (
	"fmt"
	"net/http"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	var handlerFunc types.FuncHandler

	handlerFunc = func() map[string]http.Handler {
		return map[string]http.Handler{
			types.HandlerDefault: types.NewBadHandler(),
			"api":                http.NotFoundHandler(),
			"admin":              http.NotFoundHandler(),
		}
	}

	handlers := handlerFunc()
	fmt.Printf("Total handlers: %d\n", len(handlers))

	keys := []string{types.HandlerDefault, "api", "admin"}
	for _, key := range keys {
		if _, exists := handlers[key]; exists {
			fmt.Printf("Handler key: %s\n", key)
		}
	}
}
Output:

Total handlers: 3
Handler key: default
Handler key: api
Handler key: admin
Example (HandlerDefault)

Example_handlerDefault demonstrates using the HandlerDefault constant. This shows the standard key for default handler registration.

package main

import (
	"fmt"
	"net/http"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	handlers := map[string]http.Handler{
		types.HandlerDefault: http.NotFoundHandler(),
	}

	if handler, exists := handlers[types.HandlerDefault]; exists {
		fmt.Printf("Default handler registered: %t\n", handler != nil)
	}
}
Output:

Default handler registered: true
Example (HandlerRegistration)

Example_handlerRegistration demonstrates complete handler registration. This shows a realistic multi-handler server configuration.

package main

import (
	"fmt"
	"net/http"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	createHandlers := func() types.FuncHandler {
		return func() map[string]http.Handler {
			apiHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusOK)
			})

			webHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusOK)
			})

			return map[string]http.Handler{
				types.HandlerDefault: webHandler,
				"api":                apiHandler,
			}
		}
	}

	handlerFunc := createHandlers()
	handlers := handlerFunc()

	fmt.Printf("Registered handlers: %d\n", len(handlers))

	if _, exists := handlers[types.HandlerDefault]; exists {
		fmt.Println("Default handler: configured")
	}

	if _, exists := handlers["api"]; exists {
		fmt.Println("API handler: configured")
	}
}
Output:

Registered handlers: 2
Default handler: configured
API handler: configured
Example (HandlerValidation)

Example_handlerValidation demonstrates validating handler registration. This shows a pattern for checking handler configuration.

package main

import (
	"fmt"
	"net/http"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	validateHandlers := func(handlerFunc types.FuncHandler) error {
		if handlerFunc == nil {
			return fmt.Errorf("handler function is nil")
		}

		handlers := handlerFunc()
		if handlers == nil {
			return fmt.Errorf("handlers map is nil")
		}

		if handlers[types.HandlerDefault] == nil {
			return fmt.Errorf("default handler not configured")
		}

		return nil
	}

	validFunc := func() map[string]http.Handler {
		return map[string]http.Handler{
			types.HandlerDefault: http.NotFoundHandler(),
		}
	}

	if err := validateHandlers(validFunc); err != nil {
		fmt.Printf("Validation failed: %v\n", err)
	} else {
		fmt.Println("Validation passed")
	}
}
Output:

Validation passed
Example (HandlerWithFallback)

Example_handlerWithFallback demonstrates using BadHandler as fallback. This pattern provides safe defaults when handler registration fails.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	var handlerFunc types.FuncHandler

	handlerFunc = func() map[string]http.Handler {
		return nil
	}

	handlers := handlerFunc()
	var handler http.Handler

	if handlers == nil || handlers[types.HandlerDefault] == nil {
		handler = types.NewBadHandler()
		fmt.Println("Using fallback handler")
	} else {
		handler = handlers[types.HandlerDefault]
		fmt.Println("Using configured handler")
	}

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	w := httptest.NewRecorder()
	handler.ServeHTTP(w, req)

	fmt.Printf("Status: %d\n", w.Code)
}
Output:

Using fallback handler
Status: 500
Example (ServerFiltering)

Example_serverFiltering demonstrates filtering pattern with FieldType. This shows a realistic server filtering scenario.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	type srv struct {
		name   string
		bind   string
		expose string
	}

	servers := []srv{
		{name: "api-server", bind: ":8080", expose: "https://api.example.com"},
		{name: "web-server", bind: ":8081", expose: "https://www.example.com"},
		{name: "admin-server", bind: ":8082", expose: "https://admin.example.com"},
	}

	filterByField := func(field types.FieldType, value string) []srv {
		var result []srv
		for _, s := range servers {
			var match bool
			switch field {
			case types.FieldName:
				match = s.name == value
			case types.FieldBind:
				match = s.bind == value
			case types.FieldExpose:
				match = s.expose == value
			}
			if match {
				result = append(result, s)
			}
		}
		return result
	}

	results := filterByField(types.FieldBind, ":8080")
	for _, s := range results {
		fmt.Printf("Found: %s\n", s.name)
	}
}
Output:

Found: api-server
Example (TimeoutConstants)

Example_timeoutConstants demonstrates using timeout constants. This shows how to access and use predefined timeout values.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	portTimeout := types.TimeoutWaitingPortFreeing
	stopTimeout := types.TimeoutWaitingStop

	fmt.Printf("Port freeing timeout: %v\n", portTimeout)
	fmt.Printf("Stop timeout: %v\n", stopTimeout)
}
Output:

Port freeing timeout: 3s
Stop timeout: 5s

Index

Examples

Constants

View Source
const (
	// TimeoutWaitingPortFreeing is the timeout duration for checking if a port becomes available.
	// Used when verifying port availability before binding.
	TimeoutWaitingPortFreeing = 3 * time.Second

	// TimeoutWaitingStop is the default timeout for graceful server shutdown.
	// Servers have 5 seconds to complete ongoing requests before forced termination.
	TimeoutWaitingStop = 5 * time.Second

	// BadHandlerName is the identifier string for the BadHandler.
	// Used in logging and monitoring to indicate no valid handler is configured.
	BadHandlerName = "no handler"
)
View Source
const HandlerDefault = "default"

HandlerDefault is the default key used for handler registration when no specific key is provided.

Variables

This section is empty.

Functions

func NewBadHandler

func NewBadHandler() http.Handler

NewBadHandler creates a default error handler that returns HTTP 500 Internal Server Error. This handler is used as a fallback when no valid handler is registered for a server.

Returns:

  • http.Handler: A handler that always returns 500 status code
Example

ExampleNewBadHandler demonstrates creating a fallback error handler. This is the simplest way to create a safe default handler.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	handler := types.NewBadHandler()

	req := httptest.NewRequest(http.MethodGet, "/", nil)
	w := httptest.NewRecorder()

	handler.ServeHTTP(w, req)

	fmt.Printf("Status: %d\n", w.Code)
}
Output:

Status: 500

Types

type BadHandler

type BadHandler struct{}

BadHandler is a default HTTP handler that returns 500 Internal Server Error for all requests. It's used as a fallback when no proper handler is configured for a server instance.

func (BadHandler) ServeHTTP

func (o BadHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request)

ServeHTTP implements http.Handler interface, returning HTTP 500 for all requests. This indicates that no valid handler was configured for the server.

type FieldType

type FieldType uint8

FieldType identifies server fields for filtering and listing operations. Used primarily by the pool package to filter servers by specific attributes.

Example

ExampleFieldType demonstrates basic usage of FieldType enumeration. This is the simplest use case for field identification.

package main

import (
	"fmt"

	"github.com/nabbar/golib/httpserver/types"
)

func main() {
	field := types.FieldName

	fmt.Printf("Field type: %d\n", field)
}
Output:

Field type: 0
const (
	// FieldName identifies the server name field for filtering operations.
	FieldName FieldType = iota

	// FieldBind identifies the bind address field (Listen) for filtering operations.
	FieldBind

	// FieldExpose identifies the expose URL field for filtering operations.
	FieldExpose
)

type FuncHandler

type FuncHandler func() map[string]http.Handler

FuncHandler is the function signature for handler registration. It returns a map where keys are handler identifiers and values are http.Handler instances. The "default" key or empty string "" is used when no specific handler key is configured.

Example:

func() map[string]http.Handler {
    return map[string]http.Handler{
        "":      defaultHandler,
        "api":   apiHandler,
        "admin": adminHandler,
    }
}

Jump to

Keyboard shortcuts

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