This package provides middleware components for both HTTP and gRPC services, organized by functionality. The package is structured into sub-packages to avoid naming conflicts and improve code organization.
middlewares/ ├── middlewares.go # Re-exports all public APIs for backward compatibility ├── httpmw/ # HTTP middleware (renamed from 'http' to avoid conflict with stdlib) │ ├── http.go # CORS, file type checking │ ├── http_pprof.go # Performance profiling │ └── http_prometheus.go # Prometheus metrics ├── ratelimitmw/ # Rate limiting middleware (wraps utils/ratelimit package) │ ├── ratelimit.go # Gin middleware handler │ ├── ratelimit_helper.go # Helper functions │ └── ratelimit_http.go # HTTP handler wrapper ├── circuitbreakermw/ # Circuit breaker middleware (wraps utils/circuitbreaker package) │ └── circuitbreaker.go # Gin and HTTP handler wrappers └── grpcmw/ # gRPC middleware ├── timeout.go # Timeout interceptor ├── error_handler.go # Error handling interceptor ├── logger.go # Logging interceptor ├── compression.go # Compression interceptor └── validation.go # Request validation interceptor
Note: Tracing utilities have been moved to utils/tracing/ as they are used by both HTTP and gRPC services. IP utilities have been moved to utils/iputil/ as they are general-purpose utilities.
To avoid conflicts with Go standard library packages, all sub-packages use descriptive suffixes:
httpmw - HTTP Middleware (avoids conflict with net/http)grpcmw - gRPC Middleware (unified naming with HTTP middleware)ratelimitmw - Rate Limiting Middleware (wraps utils/ratelimit package)circuitbreakermw - Circuit Breaker Middleware (wraps utils/circuitbreaker package)Note:
utils/tracing/ (used by both HTTP and gRPC)utils/iputil/ (general-purpose utilities)The framework has two rate limiting packages with distinct responsibilities:
Location: trellis.tech/trellis/common.v3/middleware/ratelimit
Purpose: Core rate limiter implementation
Provides:
Limiter interface - Defines rate limiting behaviorTokenBucketLimiter - Token bucket algorithm implementationKeyExtractor - Key extraction functions (IP, User ID, Path, etc.)Config - Rate limiter configurationUnaryRateLimitInterceptor, StreamRateLimitInterceptorUsage: Generic rate limiting that can be used in any context (HTTP, gRPC, etc.)
Location: trellis.tech/trellis/framework.v0/middlewares/ratelimitmw
Purpose: HTTP middleware wrapper for rate limiting
Provides:
RateLimitConfig - Middleware-specific configuration (includes HTTP-specific options)RateLimitHandler - Gin framework middlewareRateLimitHTTPHandler - Standard http.Handler wrapperNewRateLimitComponents - Factory function to create rate limiting componentsUsage: HTTP/Gin-specific rate limiting middleware
Dependencies: Uses utils/ratelimit package internally
Location: trellis.tech/trellis/framework.v0/middlewares/circuitbreakermw
Purpose: HTTP middleware wrapper for circuit breaking
Provides:
CircuitBreakerConfig - Middleware-specific configurationCircuitBreakerHandler - Gin framework middlewareCircuitBreakerHTTPHandler - Standard http.Handler wrapperNewCircuitBreakerComponents - Factory function to create circuit breaker componentsUsage: HTTP/Gin-specific circuit breaker middleware
Dependencies: Uses utils/circuitbreaker package internally
┌─────────────────────────────────┐ │ utils/ratelimit/ (Core Package) │ │ - Limiter interface │ │ - TokenBucketLimiter │ │ - KeyExtractor │ │ - gRPC interceptors │ └──────────────┬──────────────────┘ │ uses ▼ ┌─────────────────────────────────┐ │ middlewares/ratelimitmw/ │ │ - RateLimitConfig │ │ - RateLimitHandler (Gin) │ │ - RateLimitHTTPHandler │ │ - NewRateLimitComponents │ └─────────────────────────────────┘ ┌─────────────────────────────────────┐ │ utils/circuitbreaker/ (Core Package)│ │ - CircuitBreaker │ │ - Config │ │ - gRPC interceptors │ └──────────────┬──────────────────────┘ │ used by ▼ ┌─────────────────────────────────────┐ │ middlewares/circuitbreakermw/ │ │ - CircuitBreakerConfig │ │ - CircuitBreakerHandler (Gin) │ │ - CircuitBreakerHTTPHandler │ │ - NewCircuitBreakerComponents │ └─────────────────────────────────────┘
import (
"trellis.tech/trellis/framework.v0/middlewares/ratelimitmw"
"trellis.tech/trellis/common.v3/middleware/ratelimit"
)
// Configure rate limiting in service config
rateLimitConfig := &ratelimitmw.RateLimitConfig{
Enabled: true,
Rate: 100, // 100 requests
Period: "1s", // per second
Burst: 150, // allow burst up to 150
KeyType: ratelimit.KeyTypeIP, // limit by IP address
SkipPaths: []string{"/health", "/metrics"},
StatusCode: 429,
Message: "rate limit exceeded",
}
import (
"google.golang.org/grpc"
"trellis.tech/trellis/common.v3/middleware/ratelimit"
)
// Create rate limiter
config := ratelimit.NewConfig(100, time.Second)
limiter := ratelimit.NewTokenBucketLimiter(config)
// Create key extractor
keyExtractor := ratelimit.NewKeyExtractor(ratelimit.KeyTypeIP, nil)
// Add interceptors
server := grpc.NewServer(
grpc.UnaryInterceptor(ratelimit.UnaryRateLimitInterceptor(limiter, keyExtractor)),
grpc.StreamInterceptor(ratelimit.StreamRateLimitInterceptor(limiter, keyExtractor)),
)
import (
"trellis.tech/trellis/framework.v0/middlewares/httpmw"
)
// CORS middleware
cors, err := httpmw.LoadCorsHandler(&httpmw.CorsConfig{
AllowOrigins: []string{"http://localhost:3000"},
AllowMethods: []string{"GET", "POST"},
})
// Prometheus metrics
engine.Use(httpmw.RouterPromeHandler("my-service", &httpmw.PromeOpts{}))
// Performance profiling
httpmw.PprofHandler(&httpmw.PprofConfig{Enabled: true}, engine)
import (
"trellis.tech/trellis/framework.v0/middlewares/circuitbreakermw"
)
// Configure circuit breaker in service config
circuitBreakerConfig := &circuitbreakermw.CircuitBreakerConfig{
Enabled: true,
Name: "http-service",
MaxRequests: 1,
Interval: "60s",
Timeout: "60s",
ConsecutiveFailures: 5,
SkipPaths: []string{"/health", "/metrics"},
StatusCode: 503,
Message: "circuit breaker is open",
}
// The middleware will be automatically applied when CircuitBreakerConfig is set
import (
"trellis.tech/trellis/framework.v0/utils/iputil"
)
// Get local IP address
ip, err := iputil.GetLocalIp()
if err != nil {
// Handle error
}
import (
"trellis.tech/trellis/common.v3/middleware/tracing"
)
// Get trace ID from context
traceID := tracing.TraceIDFromContext(ctx)
// Tracing is automatically enabled for all HTTP and gRPC services
// See utils/tracing/README.md for details
import (
"google.golang.org/grpc"
"trellis.tech/trellis/framework.v0/middlewares/grpcmw"
)
// Create gRPC server with interceptors
server := grpc.NewServer(
grpc.UnaryInterceptor(
grpcmw.UnaryTimeoutInterceptor(timeoutConfig),
grpcmw.UnaryErrorHandlerInterceptor(),
grpcmw.UnaryLoggerInterceptor(loggerConfig),
),
)
The middlewares.go file in the root of the middlewares package re-exports all public APIs, allowing existing code to continue using the old import path:
import "trellis.tech/trellis/framework.v0/middlewares"
// These still work:
cfg := &middlewares.RateLimitConfig{...}
middlewares.NewRateLimitComponents(cfg)
middlewares.LoadCorsHandler(...)
However, it's recommended to use the specific sub-packages directly for better clarity:
import "trellis.tech/trellis/framework.v0/middlewares/ratelimitmw"
import "trellis.tech/trellis/framework.v0/middlewares/httpmw"
KeyTypeIP - Rate limit by client IP addressKeyTypeUserID - Rate limit by user ID (from context)KeyTypePath - Rate limit by request pathKeyTypeIPPath - Rate limit by IP + path combinationKeyTypeUserPath - Rate limit by user ID + path combinationKeyTypeCustom - Use custom extractor functionAll sub-packages include comprehensive test coverage:
# Run tests for all middlewares
go test ./middlewares/...
# Run tests for specific sub-package
go test ./middlewares/ratelimitmw
go test ./middlewares/circuitbreakermw
go test ./middlewares/httpmw
go test ./middlewares/grpcmw
If you're migrating from the old structure:
Import paths: Update imports from middlewares to specific sub-packages
middlewares.RateLimitConfig → ratelimitmw.RateLimitConfigmiddlewares.LoadCorsHandler → httpmw.LoadCorsHandlerPackage aliases: You may need to add aliases to avoid conflicts
import (
ratelimitmw "trellis.tech/trellis/framework.v0/middlewares/ratelimitmw"
"trellis.tech/trellis/common.v3/middleware/ratelimit"
)
Type references: Update type references in your code
*middlewares.RateLimitConfig → *ratelimitmw.RateLimitConfig*middlewares.CorsConfig → *httpmw.CorsConfig