Skip to content

Middleware Configuration

Anthony Bible edited this page Nov 21, 2025 · 1 revision

Middleware Configuration and Architecture

Overview

The codechunking API server implements a comprehensive middleware system built on hexagonal architecture principles. The middleware provides cross-cutting concerns including logging, security, CORS, error handling, and request validation. All middleware is located in internal/adapter/inbound/api/.

Table of Contents

Middleware Architecture

Hexagonal Architecture Integration

The middleware layer sits at the adapter/inbound boundary, intercepting HTTP requests before they reach the application core. This design ensures:

  1. Separation of Concerns: Cross-cutting concerns are isolated from business logic
  2. Testability: Each middleware can be tested independently
  3. Composability: Middleware can be mixed and matched based on needs
  4. Observability: Centralized logging and monitoring across all requests

Middleware Function Signature

All middleware follows the standard Go HTTP middleware pattern:

type Middleware func(http.Handler) http.Handler

Execution Order

Middleware is applied in reverse order for proper stacking. The middleware chain executes from outermost to innermost:

Request → Security Headers → Rate Limiting → Content Type → Security Validation → Handler
Response ← Security Headers ← Rate Limiting ← Content Type ← Security Validation ← Handler

Available Middleware

Logging Middleware

Location: internal/adapter/inbound/api/middleware.go:176

Provides request/response logging with structured fields and request ID tracking.

Features

  • Request ID Management: Generates or uses existing X-Request-ID headers
  • Correlation ID Propagation: Tracks requests across system boundaries
  • Performance Metrics: Measures request duration
  • Structured Fields: Logs method, path, status, duration, user agent, client IP
  • Query Parameter Logging: Captures URL query parameters
  • Field Chaining Optimization: Minimizes memory allocations

Usage

logger := NewDefaultLogger()
middleware := NewLoggingMiddleware(logger)
handler := middleware(yourHandler)

Context Integration

The middleware injects request IDs into the request context:

// Extract request ID from context
requestID := GetRequestID(ctx)

// Set request ID in context
ctx = SetRequestID(ctx, "custom-request-id")

Configuration

Logging behavior can be customized through the DefaultLogger:

logger := NewDefaultLogger()
contextLogger := logger.
    WithField("service", "api").
    WithField("environment", "production")

Performance Optimizations

  • Field Chain Pattern: Avoids premature map copying when creating logger contexts
  • Deferred Materialization: Only materializes field maps when actually logging
  • Response Writer Wrapping: Efficiently captures status codes without buffering

Security Middleware

Location: internal/adapter/inbound/api/middleware.go:298-424

Adds comprehensive security headers to all HTTP responses. Uses the unified security headers implementation.

Security Headers Applied

Header Default Value Purpose
X-Content-Type-Options nosniff Prevents MIME type sniffing
X-Frame-Options DENY Prevents clickjacking attacks
X-XSS-Protection 1; mode=block Enables browser XSS protection
Referrer-Policy strict-origin-when-cross-origin Controls referrer information
Content-Security-Policy default-src 'self' Restricts resource loading
Strict-Transport-Security max-age=31536000; includeSubDomains Enforces HTTPS (when using TLS)

Basic Usage

// Use default security headers
middleware := NewSecurityMiddleware()
handler := middleware(yourHandler)

Advanced Configuration

// Custom security configuration
config := &SecurityHeadersConfig{
    ReferrerPolicy: "no-referrer",
    CSPPolicy:      "comprehensive", // or "basic" or custom string
    HStsEnabled:    boolPtr(true),
    HStsMaxAge:     63072000, // 2 years
    HStsSubdomains: boolPtr(true),
    HStsPreload:    boolPtr(true),
    XFrameOptions:  "SAMEORIGIN",
    XContentType:   "nosniff",
    XXSSProtection: "1; mode=block",
}

middleware := NewUnifiedSecurityMiddleware(config)

CSP Policies

Three CSP policy levels are available:

  1. Basic (default): default-src 'self'
  2. Comprehensive: default-src 'self'; script-src 'self'; object-src 'none'
  3. Custom: Provide your own CSP string

HSTS Configuration

HSTS (HTTP Strict Transport Security) is only applied when:

  • HStsEnabled is set to true
  • The request is made over TLS (r.TLS != nil)
// Disable HSTS
config := &SecurityHeadersConfig{
    HStsEnabled: boolPtr(false),
}

// Enable with custom settings
config := &SecurityHeadersConfig{
    HStsEnabled:    boolPtr(true),
    HStsMaxAge:     31536000,      // 1 year
    HStsSubdomains: boolPtr(true), // Include subdomains
    HStsPreload:    boolPtr(true), // Enable HSTS preload
}

CORS Middleware

Location: internal/adapter/inbound/api/middleware.go:454-495

Handles Cross-Origin Resource Sharing (CORS) for browser-based API clients.

Features

  • Preflight Request Handling: Responds to OPTIONS requests
  • Configurable Origins: Control which origins can access the API
  • Method Whitelisting: Specify allowed HTTP methods
  • Header Management: Configure allowed request headers
  • Cache Control: Set preflight response cache duration

Default Configuration

config := CORSConfig{
    AllowedOrigins: []string{"*"},
    AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
    AllowedHeaders: []string{"Content-Type", "Authorization"},
    MaxAge:         86400, // 24 hours
}

Usage Examples

Basic (allow all origins):

middleware := NewCORSMiddleware()

Custom configuration:

config := CORSConfig{
    AllowedOrigins: []string{"https://app.example.com", "https://admin.example.com"},
    AllowedMethods: []string{"GET", "POST"},
    AllowedHeaders: []string{"Content-Type", "Authorization", "X-API-Key"},
    MaxAge:         3600, // 1 hour
}

middleware := NewCORSMiddlewareWithConfig(config)

Request Header Passthrough

The middleware automatically appends any requested headers from Access-Control-Request-Headers to maintain backward compatibility with existing clients.


Error Handling Middleware

Location: internal/adapter/inbound/api/middleware.go:222-271

Provides centralized panic recovery and error response formatting.

Features

  • Panic Recovery: Catches and logs panics in HTTP handlers
  • Context Cancellation Handling: Properly handles cancelled requests
  • Structured Error Responses: Returns JSON error responses
  • Request ID Propagation: Includes request IDs in error responses
  • Comprehensive Logging: Logs panic details with request context

Behavior

On Panic:

{
  "error": "Internal Server Error",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

On Context Cancellation:

{
  "error": "Request cancelled",
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Logging Output

When a panic occurs, the middleware logs:

{
  "request_id": "550e8400-e29b-41d4-a716-446655440000",
  "method": "POST",
  "path": "/repositories",
  "panic": "runtime error: index out of range"
}

Usage

middleware := NewErrorHandlingMiddleware()
handler := middleware(yourHandler)

Advanced Middleware

Structured Logging Middleware

Location: internal/adapter/inbound/api/middleware/logging_middleware.go:278

A production-grade logging middleware with advanced features including async logging, object pooling, sampling, and resource monitoring.

Configuration

config := LoggingConfig{
    LogLevel:              "INFO",           // DEBUG, INFO, WARN, ERROR
    EnableRequestBody:     false,            // Log request bodies
    EnableResponseBody:    false,            // Log response bodies
    MaxBodySize:           1024 * 64,        // 64KB max body size
    SensitiveHeaders:      []string{"Authorization", "X-API-Key"},
    SlowRequestThreshold:  500 * time.Millisecond,
    EnablePerfMetrics:     true,
    EnablePanicLogs:       true,
    EnableSecurityLogging: true,
    SuspiciousPatterns:    []string{"bot", "scanner"},
    ExcludePaths:          []string{"/health", "/metrics"},
    SampleRate:            1.0,              // 1.0 = log everything, 0.5 = log 50%

    // Performance optimizations
    EnableObjectPooling:   true,
    EnableAsyncLogging:    true,
    AsyncBufferSize:       1000,
    MaxMemoryMB:           512,
    MaxRequestsPerSecond:  10000,
    EnableResourceMetrics: true,
}

middleware := NewStructuredLoggingMiddleware(config)

Features

1. Async Logging

Process log writes in a background goroutine to minimize request latency:

config := LoggingConfig{
    EnableAsyncLogging: true,
    AsyncBufferSize:    1000, // Buffer up to 1000 log entries
}
2. Object Pooling

Reduce memory allocations by reusing log entry objects:

config := LoggingConfig{
    EnableObjectPooling: true,
}
3. Request Sampling

Reduce logging volume in high-traffic environments:

config := LoggingConfig{
    SampleRate: 0.1, // Log only 10% of requests
}
4. Path Exclusions

Skip logging for health checks and metrics endpoints:

config := LoggingConfig{
    ExcludePaths: []string{"/health", "/metrics", "/ready"},
}
5. Performance Metrics

Track request performance and identify slow requests:

config := LoggingConfig{
    EnablePerfMetrics:    true,
    SlowRequestThreshold: 500 * time.Millisecond,
}
6. Security Logging

Detect and log suspicious request patterns:

config := LoggingConfig{
    EnableSecurityLogging: true,
    SuspiciousPatterns:    []string{"bot", "scanner", "crawler"},
}

Security checks include:

  • Suspicious user agents
  • Missing authorization on sensitive endpoints
  • Potential SQL injection patterns
7. Resource Monitoring

Monitor memory usage and request rates:

config := LoggingConfig{
    MaxMemoryMB:           512,
    MaxRequestsPerSecond:  10000,
    EnableResourceMetrics: true,
}

Log Entry Format

{
  "timestamp": "2025-11-21T10:30:45Z",
  "level": "INFO",
  "message": "HTTP GET /repositories - 200",
  "correlation_id": "550e8400-e29b-41d4-a716-446655440000",
  "component": "http-middleware",
  "operation": "http_request",
  "duration": 123.45,
  "request": {
    "method": "GET",
    "path": "/repositories",
    "status": 200,
    "duration": 123.45,
    "request_size": 0,
    "response_size": 1024,
    "client_ip": "192.168.1.100",
    "user_agent": "Mozilla/5.0...",
    "content_type": "application/json"
  }
}

Correlation ID Management

Extract correlation IDs from context:

import "codechunking/internal/adapter/inbound/api/middleware"

correlationID := middleware.GetCorrelationIDFromContext(ctx)

Performance Metrics

Retrieve middleware performance metrics:

metrics := middleware.GetMiddlewarePerformanceMetrics()
// Returns map with:
// - total_requests
// - total_bytes
// - average_latency_ns
// - errors_count
// - dropped_requests
// - memory_usage_mb
// - last_memory_check

Security Validation Middleware

Location: internal/adapter/inbound/api/security_middleware.go:38

Provides comprehensive input validation to protect against common web attacks.

Security Checks

  1. SQL Injection Detection: Scans query parameters and JSON fields
  2. XSS Prevention: Validates request data for malicious scripts
  3. Header Injection Prevention: Detects CRLF injection in headers
  4. Path Traversal Protection: Prevents directory traversal attacks
  5. Payload Size Limits: Enforces 64KB request body limit
  6. JSON Validation: Ensures well-formed JSON requests

Usage

middleware := NewSecurityValidationMiddleware()
handler := middleware(yourHandler)

Validation Process

The middleware validates requests in the following order:

  1. Query Parameters → Checks for SQL injection patterns
  2. Request Headers → Detects CRLF injection
  3. Request Body (POST/PUT) → Validates JSON content and size

Error Responses

SQL Injection Detected:

{
  "error": "malicious SQL detected",
  "code": 400,
  "message": "Security validation failed"
}

Payload Too Large:

{
  "error": "payload too large",
  "code": 413,
  "message": "Security validation failed"
}

Multiple Violations:

{
  "error": "multiple security violations",
  "code": 400,
  "message": "Security validation failed"
}

SQL Injection Patterns

The validation uses internal/application/common.ValidateQueryParameters() which checks for:

  • SQL keywords: SELECT, INSERT, UPDATE, DELETE, DROP, UNION
  • Comment sequences: --, /*, */
  • String termination attempts: ', "
  • Boolean-based injection: OR 1=1, AND 1=1

JSON Field Validation

Recursively validates all JSON fields using internal/application/common.ValidateJSONField():

// Validates nested JSON structures
{
  "user": {
    "name": "John",           // ✓ Valid
    "query": "'; DROP TABLE"  // ✗ SQL injection detected
  }
}

Rate Limiting Middleware

Location: internal/adapter/inbound/api/security_middleware.go:192

Implements per-client IP rate limiting to prevent abuse.

Configuration

config := RateLimitConfig{
    RequestsPerMinute: 60,    // Max requests per minute
    BurstSize:         10,    // Burst allowance
    WindowSize:        "1m",  // Time window
}

middleware := NewRateLimitingMiddleware(config)

Features

  • Per-Client Tracking: Separate limits for each client IP
  • Sliding Window: Uses 1-minute rolling window
  • Thread-Safe: Safe for concurrent requests
  • Automatic Cleanup: Removes expired request records

Rate Limit Response

When rate limit is exceeded:

{
  "error": "rate limit exceeded",
  "code": 429,
  "message": "Security validation failed"
}

HTTP Status: 429 Too Many Requests

Client IP Detection

Uses internal/adapter/inbound/api/netutil.ClientIP() which checks:

  1. X-Forwarded-For header (first IP)
  2. X-Real-IP header
  3. Remote address from connection

Internal State Management

type ClientState struct {
    requests []time.Time  // Request timestamps
    mutex    sync.Mutex   // Thread-safe access
}

Content Type Validation

Location: internal/adapter/inbound/api/security_middleware.go:244

Ensures only supported content types are processed.

Features

  • JSON-Only Enforcement: Accepts only application/json content type
  • POST/PUT Validation: Only validates requests with bodies
  • Flexible Matching: Handles charset parameters (e.g., application/json; charset=utf-8)

Usage

middleware := NewContentTypeValidationMiddleware()
handler := middleware(yourHandler)

Error Response

When unsupported content type is detected:

{
  "error": "unsupported content type",
  "code": 415,
  "message": "Security validation failed"
}

HTTP Status: 415 Unsupported Media Type

Accepted Content Types

  • application/json
  • application/json; charset=utf-8
  • Any application/json variant with parameters

Middleware Chain Composition

Standard Middleware Chain

The default server uses this middleware stack (applied in reverse):

builder := NewServerBuilder(config).
    WithHealthService(healthService).
    WithRepositoryService(repoService).
    WithErrorHandler(errorHandler).
    WithDefaultMiddleware()  // Applies standard chain

Default middleware order (outermost to innermost):

  1. Error Handling → Catches panics
  2. CORS → Handles cross-origin requests
  3. Logging → Tracks requests
  4. Security Headers → Adds security headers

Security Middleware Stack

For maximum security, use the comprehensive security stack:

securityStack := CreateSecurityMiddlewareStack()
handler := securityStack(yourHandler)

Security stack order (outermost to innermost):

  1. Security Headers → Adds protection headers
  2. Rate Limiting → Prevents abuse (10 req/min)
  3. Content Type Validation → Ensures JSON only
  4. Security Validation → Validates input

Custom Middleware Chains

Build custom chains using NewMiddlewareChain:

customChain := NewMiddlewareChain(
    NewSecurityMiddleware(),
    NewLoggingMiddleware(logger),
    NewRateLimitingMiddleware(rateLimitConfig),
)

handler := customChain(yourHandler)

Builder Pattern

Use the builder for fine-grained control:

server, err := NewServerBuilder(config).
    WithHealthService(healthService).
    WithRepositoryService(repoService).
    WithErrorHandler(errorHandler).
    WithMiddleware(NewSecurityMiddleware()).
    WithMiddleware(NewLoggingMiddleware(logger)).
    WithMiddleware(customMiddleware).
    Build()

Configuration Reference

Environment Variables

Middleware behavior can be influenced by configuration:

Variable Default Description
CODECHUNK_API_HOST 0.0.0.0 API server host
CODECHUNK_API_PORT 8080 API server port
CODECHUNK_API_READ_TIMEOUT 30s Request read timeout
CODECHUNK_API_WRITE_TIMEOUT 30s Response write timeout

Programmatic Configuration

Configure middleware through the builder:

config := &config.Config{
    API: config.APIConfig{
        Host:         "localhost",
        Port:         "8080",
        ReadTimeout:  30 * time.Second,
        WriteTimeout: 30 * time.Second,
    },
}

server, _ := NewServerBuilder(config).
    WithDefaultMiddleware().
    Build()

Usage Examples

Basic API Server

package main

import (
    "codechunking/internal/adapter/inbound/api"
    "codechunking/internal/config"
    "context"
)

func main() {
    cfg := config.Load()

    server, err := api.NewServer(
        cfg,
        healthService,
        repoService,
        errorHandler,
    )
    if err != nil {
        panic(err)
    }

    ctx := context.Background()
    if err := server.Start(ctx); err != nil {
        panic(err)
    }
}

Custom Middleware Server

// Custom logging middleware
func customLogger(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Printf("Custom: %s %s", r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

server, err := api.NewServerBuilder(config).
    WithHealthService(healthService).
    WithRepositoryService(repoService).
    WithErrorHandler(errorHandler).
    WithMiddleware(api.NewSecurityMiddleware()).
    WithMiddleware(customLogger).
    WithMiddleware(api.NewCORSMiddleware()).
    Build()

Production Server with Full Security

// Rate limiting configuration
rateLimitConfig := api.RateLimitConfig{
    RequestsPerMinute: 100,
    BurstSize:         20,
    WindowSize:        "1m",
}

// Security headers configuration
securityConfig := &api.SecurityHeadersConfig{
    ReferrerPolicy: "no-referrer",
    CSPPolicy:      "comprehensive",
    HStsEnabled:    boolPtr(true),
    HStsMaxAge:     63072000, // 2 years
    HStsSubdomains: boolPtr(true),
    HStsPreload:    boolPtr(true),
}

// Structured logging configuration
loggingConfig := api.LoggingConfig{
    LogLevel:              "INFO",
    EnablePerfMetrics:     true,
    SlowRequestThreshold:  500 * time.Millisecond,
    EnableSecurityLogging: true,
    EnableAsyncLogging:    true,
    EnableObjectPooling:   true,
    SampleRate:            1.0,
    ExcludePaths:          []string{"/health"},
}

server, err := api.NewServerBuilder(config).
    WithHealthService(healthService).
    WithRepositoryService(repoService).
    WithSearchService(searchService).
    WithErrorHandler(errorHandler).
    WithMiddleware(api.NewUnifiedSecurityMiddleware(securityConfig)).
    WithMiddleware(api.NewRateLimitingMiddleware(rateLimitConfig)).
    WithMiddleware(api.NewContentTypeValidationMiddleware()).
    WithMiddleware(api.NewSecurityValidationMiddleware()).
    WithMiddleware(api.NewStructuredLoggingMiddleware(loggingConfig)).
    WithMiddleware(api.NewCORSMiddleware()).
    WithMiddleware(api.NewErrorHandlingMiddleware()).
    Build()

Testing with Custom Logger

func TestMyHandler(t *testing.T) {
    var logOutput strings.Builder
    logger := api.NewTestLogger(&logOutput)

    middleware := api.NewLoggingMiddleware(logger)
    handler := middleware(myHandler)

    req := httptest.NewRequest("GET", "/test", nil)
    rec := httptest.NewRecorder()

    handler.ServeHTTP(rec, req)

    assert.Contains(t, logOutput.String(), "GET /test")
}

Best Practices

1. Middleware Ordering

Always apply middleware in the correct order:

// ✓ Correct: Error handling catches panics from all middleware
WithMiddleware(NewErrorHandlingMiddleware()).
WithMiddleware(NewCORSMiddleware()).
WithMiddleware(NewLoggingMiddleware(logger)).
WithMiddleware(NewSecurityMiddleware())

// ✗ Incorrect: Panics in logging won't be caught
WithMiddleware(NewLoggingMiddleware(logger)).
WithMiddleware(NewErrorHandlingMiddleware())

2. Request ID Propagation

Always propagate request IDs to downstream services:

func myHandler(w http.ResponseWriter, r *http.Request) {
    requestID := api.GetRequestID(r.Context())

    // Pass to downstream service
    downstreamReq, _ := http.NewRequest("POST", "http://service/api", body)
    downstreamReq.Header.Set("X-Request-ID", requestID)
}

3. Sensitive Header Handling

Configure sensitive headers to avoid logging credentials:

config := LoggingConfig{
    SensitiveHeaders: []string{
        "Authorization",
        "X-API-Key",
        "Cookie",
        "X-Auth-Token",
    },
}

4. Production Security Stack

Always use the full security stack in production:

// Production
handler := CreateSecurityMiddlewareStack()(yourHandler)

// Development (optional - can skip some validation)
handler := NewLoggingMiddleware(logger)(yourHandler)

5. Rate Limiting Configuration

Adjust rate limits based on your traffic patterns:

// Public API - restrictive
RateLimitConfig{
    RequestsPerMinute: 60,
    BurstSize:         10,
}

// Internal API - permissive
RateLimitConfig{
    RequestsPerMinute: 1000,
    BurstSize:         100,
}

6. CORS Configuration

Development:

config := CORSConfig{
    AllowedOrigins: []string{"*"},
}

Production:

config := CORSConfig{
    AllowedOrigins: []string{
        "https://app.example.com",
        "https://admin.example.com",
    },
    AllowedMethods: []string{"GET", "POST"},
    AllowedHeaders: []string{"Content-Type", "Authorization"},
}

7. Error Handling

Let the error handling middleware manage panics:

// ✓ Correct: Let middleware handle panic
func handler(w http.ResponseWriter, r *http.Request) {
    result := somethingThatMightPanic()
    json.NewEncoder(w).Encode(result)
}

// ✗ Incorrect: Don't add redundant panic recovery
func handler(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if r := recover(); r != nil {
            // Middleware already handles this
        }
    }()
}

8. Testing Middleware

Test middleware in isolation before integration:

func TestMyMiddleware(t *testing.T) {
    nextCalled := false
    next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        nextCalled = true
        w.WriteHeader(http.StatusOK)
    })

    middleware := MyMiddleware()
    handler := middleware(next)

    req := httptest.NewRequest("GET", "/test", nil)
    rec := httptest.NewRecorder()

    handler.ServeHTTP(rec, req)

    assert.True(t, nextCalled)
    assert.Equal(t, http.StatusOK, rec.Code)
}

9. Performance Optimization

Use async logging and object pooling in high-traffic scenarios:

config := LoggingConfig{
    EnableAsyncLogging:  true,
    EnableObjectPooling: true,
    SampleRate:          0.1, // Log 10% in very high traffic
}

10. Security Headers for HTTPS

Only enable HSTS when serving over HTTPS:

config := &SecurityHeadersConfig{
    HStsEnabled:    boolPtr(true),  // Only works with TLS
    HStsMaxAge:     31536000,
    HStsSubdomains: boolPtr(true),
}

Related Documentation

Performance Considerations

Memory Usage

The middleware system is designed for efficiency:

  • Field Chaining: Logging middleware uses field chains to avoid premature map copying
  • Object Pooling: Structured logging middleware can reuse log entry objects
  • Response Buffering: Only buffers response body when needed

Latency Impact

Typical middleware overhead per request:

Middleware Overhead
Logging < 100μs
Security Headers < 10μs
CORS < 10μs
Error Handling < 5μs
Security Validation 100-500μs (depends on payload)
Rate Limiting 10-50μs

Total typical overhead: < 1ms per request

High-Traffic Optimization

For systems handling > 10,000 req/s:

config := LoggingConfig{
    EnableAsyncLogging:  true,   // Process logs in background
    EnableObjectPooling: true,   // Reuse log objects
    SampleRate:          0.1,    // Log only 10% of requests
    ExcludePaths:        []string{"/health", "/metrics"},
}

Troubleshooting

Request ID Not Propagating

Problem: Request IDs not appearing in logs

Solution: Ensure logging middleware is applied:

WithMiddleware(NewLoggingMiddleware(logger))

CORS Errors in Browser

Problem: Browser shows CORS errors

Solution: Verify CORS middleware is applied and configured:

config := CORSConfig{
    AllowedOrigins: []string{"https://your-frontend.com"},
    AllowedMethods: []string{"GET", "POST", "OPTIONS"},
}
WithMiddleware(NewCORSMiddlewareWithConfig(config))

Rate Limiting Too Aggressive

Problem: Legitimate clients being rate limited

Solution: Adjust rate limit configuration:

config := RateLimitConfig{
    RequestsPerMinute: 120,  // Increase limit
    BurstSize:         30,   // Increase burst
}

High Memory Usage

Problem: Middleware consuming too much memory

Solution: Enable object pooling and sampling:

config := LoggingConfig{
    EnableObjectPooling: true,
    SampleRate:          0.5,  // Log 50% of requests
}

Security Headers Not Applied

Problem: Security headers missing from responses

Solution: Ensure security middleware is applied:

WithMiddleware(NewSecurityMiddleware())

Migration Guide

From Legacy Middleware

If you're using the old middleware pattern:

Before:

mux := http.NewServeMux()
handler := loggingMiddleware(corsMiddleware(mux))

After:

server, _ := api.NewServerBuilder(config).
    WithHealthService(healthService).
    WithRepositoryService(repoService).
    WithErrorHandler(errorHandler).
    WithDefaultMiddleware().
    Build()

Adding Custom Middleware

Before:

handler := customMiddleware(defaultHandler)

After:

server, _ := api.NewServerBuilder(config).
    WithDefaultMiddleware().
    WithMiddleware(customMiddleware).
    Build()

See Also

  • Source Code:
    • internal/adapter/inbound/api/middleware.go - Core middleware
    • internal/adapter/inbound/api/security_middleware.go - Security middleware
    • internal/adapter/inbound/api/middleware/logging_middleware.go - Advanced logging
  • Tests:
    • internal/adapter/inbound/api/middleware_test.go
    • internal/adapter/inbound/api/security_middleware_test.go
    • internal/adapter/inbound/api/security_integration_test.go

Clone this wiki locally