Middleware
Middleware in Rue allows you to execute code before and after request handlers. Rue comes with several built-in middleware and makes it easy to create custom ones.
Using Middleware
Apply middleware globally or to specific route groups:
go
r := rue.New()
// Global middleware
r.Use(rue.Logger())
r.Use(rue.Recovery())
// Group-specific middleware
api := r.Group("/api")
api.Use(rue.CORS())
{
api.GET("/users", listUsers)
}
// Route-specific middleware
r.GET("/admin", adminOnly(), adminHandler)
Logger
Logs HTTP requests with timing information:
go
// Default logger
r.Use(rue.Logger())
// With configuration
r.Use(rue.LoggerWithConfig(rue.LoggerConfig{
SkipPaths: []string{"/health", "/metrics"},
}))
Output example:
[RUE] 2024/01/15 - 10:30:45 | 200 | 1.234ms | 192.168.1.1 | GET /api/users
Recovery
Recovers from panics and returns a 500 error:
go
r.Use(rue.Recovery())
CORS
Handle Cross-Origin Resource Sharing:
go
// Default CORS (allows all origins)
r.Use(rue.CORS())
// Custom configuration
r.Use(rue.CORSWithConfig(rue.CORSConfig{
AllowOrigins: []string{"https://example.com", "https://app.example.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
AllowHeaders: []string{"Origin", "Content-Type", "Authorization"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
MaxAge: 86400,
}))
Rate Limiter
Limit request rates per client:
go
// Simple rate limiter: 10 requests/second, burst of 20
r.Use(rue.RateLimiter(10, 20))
// Custom configuration
r.Use(rue.RateLimiterWithConfig(rue.RateLimiterConfig{
Rate: 100, // 100 requests per second
Burst: 200, // Allow burst of 200
KeyFunc: func(c *rue.Context) string {
// Rate limit by API key instead of IP
return c.GetHeader("X-API-Key")
},
}))
JWT Authentication
Validate JSON Web Tokens:
go
secret := []byte("your-secret-key")
// Generate a token
claims := &rue.JWTClaims{
Subject: "user123",
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
Custom: map[string]any{
"role": "admin",
"permissions": []string{"read", "write"},
},
}
token, err := rue.GenerateToken(claims, secret)
// Protect routes with JWT middleware
api := r.Group("/api")
api.Use(rue.JWT(secret))
{
api.GET("/profile", func(c *rue.Context) {
// Access claims from context
claims, _ := c.Get("jwt_claims")
jwtClaims := claims.(*rue.JWTClaims)
c.JSON(http.StatusOK, rue.H{
"user_id": jwtClaims.Subject,
"role": jwtClaims.Custom["role"],
})
})
}
API Key Authentication
Validate API keys from headers or query parameters:
go
// Simple API key validation
r.Use(rue.APIKey(func(key string) bool {
validKeys := map[string]bool{
"key1": true,
"key2": true,
}
return validKeys[key]
}))
// Custom configuration
r.Use(rue.APIKeyWithConfig(rue.APIKeyConfig{
KeyLookup: "header:X-API-Key", // or "query:api_key"
Validator: func(key string) bool {
// Validate against database
return db.ValidateAPIKey(key)
},
}))
Compression
Compress responses with Gzip or Brotli:
go
// Auto-select best compression (prefers Brotli)
r.Use(rue.Compress())
// Gzip only
r.Use(rue.Gzip())
// Brotli only
r.Use(rue.Brotli())
Custom Middleware
Create your own middleware:
go
func RequestID() rue.HandlerFunc {
return func(c *rue.Context) {
// Before request
requestID := uuid.New().String()
c.Set("request_id", requestID)
c.SetHeader("X-Request-ID", requestID)
c.Next() // Process request
// After request
// Access response status, timing, etc.
}
}
func Timing() rue.HandlerFunc {
return func(c *rue.Context) {
start := time.Now()
c.Next()
duration := time.Since(start)
c.SetHeader("X-Response-Time", duration.String())
log.Printf("Request took %v", duration)
}
}
// Use custom middleware
r.Use(RequestID())
r.Use(Timing())
Middleware Order
Middleware executes in the order they are added:
go
r.Use(A()) // Executes first (before)
r.Use(B()) // Executes second (before)
r.Use(C()) // Executes third (before)
// Request flow:
// A (before) -> B (before) -> C (before) -> Handler -> C (after) -> B (after) -> A (after)
💡 Best Practice
Place error handling middleware (Recovery) first, then logging, then authentication, then business logic middleware.
Aborting Requests
Stop request processing in middleware:
go
func AuthRequired() rue.HandlerFunc {
return func(c *rue.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatus(http.StatusUnauthorized)
return // Important: return after abort
}
user, err := validateToken(token)
if err != nil {
c.AbortWithError(http.StatusUnauthorized, err)
return
}
c.Set("user", user)
c.Next()
}
}