Middleware
The application uses Fiber middleware for request processing, authentication, logging, and more.
Core Middleware
1. Logger Middleware
Logs all HTTP requests and responses.
Features:
- Request method and path
- Response status code
- Response time
- Request ID for tracing
Registration:
middleware.Register(app, cfg)2. Recovery Middleware
Recovers from panics and returns 500 error.
Features:
- Panic recovery
- Error logging
- Graceful error responses
3. CORS Middleware
Handles Cross-Origin Resource Sharing.
Configuration:
- Allows specific origins
- Configurable headers
- Configurable methods
4. Request ID Middleware
Adds unique request ID to each request.
Usage:
- Request ID in response headers
- Request ID in logs
- Request tracing
Authentication Middleware
Telegram Auth Middleware
Validates Telegram authentication.
Function: TelegramAuthMiddlewareFunc(cfg)
Behavior:
- Validates
X-Telegram-Authheader - Extracts user information
- Attaches user context to request
- Returns 401 if invalid
Usage:
app.Get("/protected",
middleware.TelegramAuthMiddlewareFunc(cfg),
handler.Protected)Optional Telegram Auth Middleware
Optional Telegram authentication.
Function: OptionalTelegramAuthMiddlewareFunc(cfg)
Behavior:
- Validates auth if header present
- Proceeds without auth if header missing
- Attaches user context if authenticated
Usage:
app.Get("/public",
middleware.OptionalTelegramAuthMiddlewareFunc(cfg),
handler.Public)Admin API Key Middleware
Validates admin API key.
Function: AdminAPIKeyAuth(cfg)
Behavior:
- Validates
X-API-Keyheader - Compares with
ADMIN_API_KEYfrom config - Returns 401 if invalid
Usage:
admin := app.Group("/admin", middleware.AdminAPIKeyAuth(cfg))Admin JWT Middleware
Validates admin JWT tokens.
Function: AdminAuthMiddleware(cfg, jwtService)
Behavior:
- Validates JWT token
- Checks admin permissions
- Returns 401 if invalid
Usage:
admin := app.Group("/admin",
middleware.AdminAuthMiddleware(cfg, jwtService))Rate Limiting Middleware
Rate Limit Middleware
Limits request rate per user/IP.
Function: RateLimitMiddleware(config, deps)
Configuration:
config := middleware.RateLimitConfig{
Max: 100, // Max requests
Expiration: time.Minute, // Time window
KeyGenerator: func(c *fiber.Ctx) string {
// Generate key from request
},
}Usage:
app.Post("/api/v1/connections",
middleware.RateLimitMiddleware(config, deps),
handler.CreateConnection)Features:
- Redis-based rate limiting
- Per-user/IP limits
- Configurable limits
- Custom key generation
Custom Middleware
Request Validation Middleware
Validates request bodies.
Example:
func ValidateRequest(validator *validator.Validate) fiber.Handler {
return func(c *fiber.Ctx) error {
var req MyRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(400).JSON(fiber.Map{
"error": "Invalid request body",
})
}
if err := validator.Struct(&req); err != nil {
return c.Status(400).JSON(fiber.Map{
"error": "Validation failed",
"details": err.Error(),
})
}
c.Locals("validated_request", &req)
return c.Next()
}
}Error Handling Middleware
Centralized error handling.
Example:
func ErrorHandler(c *fiber.Ctx, err error) error {
code := fiber.StatusInternalServerError
message := "Internal Server Error"
if e, ok := err.(*fiber.Error); ok {
code = e.Code
message = e.Message
}
return c.Status(code).JSON(fiber.Map{
"error": message,
"code": fmt.Sprintf("ERR_%d", code),
})
}Middleware Order
Middleware is executed in registration order:
- Recovery - Catch panics first
- Logger - Log all requests
- Request ID - Add request ID
- CORS - Handle CORS
- Authentication - Validate auth
- Rate Limiting - Check rate limits
- Handler - Process request
Middleware Registration
All middleware is registered in internal/middleware/middleware.go:
func Register(app *fiber.App, cfg *config.Config) {
// Recovery
app.Use(recover.New())
// Logger
app.Use(logger.New())
// Request ID
app.Use(requestid.New())
// CORS
app.Use(cors.New(cors.Config{
AllowOrigins: "*",
AllowMethods: "GET,POST,PUT,DELETE,OPTIONS",
AllowHeaders: "Content-Type,Authorization,X-API-Key,X-Telegram-Auth",
}))
}Accessing Context
Getting User from Context
func handler(c *fiber.Ctx) error {
userID := c.Locals("user_id")
telegramID := c.Locals("telegram_id")
// Use user information
}Getting Request ID
func handler(c *fiber.Ctx) error {
requestID := c.Locals("requestid")
// Use request ID for logging
}Best Practices
- Order matters - Register middleware in correct order
- Fail fast - Authentication before business logic
- Error handling - Handle errors gracefully
- Logging - Log important events
- Performance - Keep middleware lightweight
- Security - Validate all inputs
- Rate limiting - Protect sensitive endpoints
Testing Middleware
Test Authentication Middleware
func TestTelegramAuth(t *testing.T) {
app := fiber.New()
app.Get("/test",
middleware.TelegramAuthMiddlewareFunc(cfg),
func(c *fiber.Ctx) error {
return c.SendString("OK")
})
// Test with valid auth
req := httptest.NewRequest("GET", "/test", nil)
req.Header.Set("X-Telegram-Auth", validAuth)
resp, _ := app.Test(req)
assert.Equal(t, 200, resp.StatusCode)
// Test with invalid auth
req = httptest.NewRequest("GET", "/test", nil)
resp, _ = app.Test(req)
assert.Equal(t, 401, resp.StatusCode)
}