feat: add configurable test mode and rate limiting
- Add TestMode, RateLimitEnabled, RequestsPerMinute to Config - Add getEnvBool() and getEnvInt() helper functions - Update rate limiter to support enabled/disabled state - Pass test environment variables through docker-compose - Configure rate limiter dynamically in main.go This allows disabling rate limiting for integration testing while maintaining security in production environments.
This commit is contained in:
+6
-1
@@ -67,7 +67,12 @@ func main() {
|
|||||||
e.Use(ratelimit.RequestTracingMiddleware(cfg))
|
e.Use(ratelimit.RequestTracingMiddleware(cfg))
|
||||||
|
|
||||||
// Rate limiter for auth endpoints
|
// Rate limiter for auth endpoints
|
||||||
rateLimiter := ratelimit.NewRateLimiter(ratelimit.DefaultRateLimiterConfig())
|
rateLimiterConfig := ratelimit.RateLimiterConfig{
|
||||||
|
Enabled: cfg.RateLimitEnabled,
|
||||||
|
RequestsPerMinute: cfg.RequestsPerMinute,
|
||||||
|
CleanupInterval: 5 * time.Minute,
|
||||||
|
}
|
||||||
|
rateLimiter := ratelimit.NewRateLimiter(rateLimiterConfig)
|
||||||
rateLimitMiddleware := ratelimit.RateLimiterMiddleware(rateLimiter)
|
rateLimitMiddleware := ratelimit.RateLimiterMiddleware(rateLimiter)
|
||||||
|
|
||||||
// Auth routes (no auth required, but rate limited)
|
// Auth routes (no auth required, but rate limited)
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ services:
|
|||||||
DATABASE_NAME: bookmann
|
DATABASE_NAME: bookmann
|
||||||
JWT_SECRET: ${JWT_SECRET}
|
JWT_SECRET: ${JWT_SECRET}
|
||||||
SERVER_PORT: 8765
|
SERVER_PORT: 8765
|
||||||
|
TEST_MODE: ${TEST_MODE:-false}
|
||||||
|
RATE_LIMIT_ENABLED: ${RATE_LIMIT_ENABLED:-true}
|
||||||
|
REQUESTS_PER_MINUTE: ${REQUESTS_PER_MINUTE:-10}
|
||||||
ports:
|
ports:
|
||||||
- "8765:8765"
|
- "8765:8765"
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@@ -14,6 +15,9 @@ type Config struct {
|
|||||||
DatabaseUser string
|
DatabaseUser string
|
||||||
DatabasePassword string
|
DatabasePassword string
|
||||||
DatabaseName string
|
DatabaseName string
|
||||||
|
TestMode bool
|
||||||
|
RateLimitEnabled bool
|
||||||
|
RequestsPerMinute int
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig() *Config {
|
func LoadConfig() *Config {
|
||||||
@@ -26,6 +30,9 @@ func LoadConfig() *Config {
|
|||||||
DatabaseName: getEnv("DATABASE_NAME", "bookmann"),
|
DatabaseName: getEnv("DATABASE_NAME", "bookmann"),
|
||||||
JWTSecret: getEnv("JWT_SECRET", "your-secret-key"),
|
JWTSecret: getEnv("JWT_SECRET", "your-secret-key"),
|
||||||
UploadPath: getEnv("UPLOAD_PATH", "./uploads"),
|
UploadPath: getEnv("UPLOAD_PATH", "./uploads"),
|
||||||
|
TestMode: getEnvBool("TEST_MODE", false),
|
||||||
|
RateLimitEnabled: getEnvBool("RATE_LIMIT_ENABLED", true),
|
||||||
|
RequestsPerMinute: getEnvInt("REQUESTS_PER_MINUTE", 10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,3 +47,23 @@ func getEnv(key, defaultValue string) string {
|
|||||||
}
|
}
|
||||||
return defaultValue
|
return defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getEnvBool(key string, defaultValue bool) bool {
|
||||||
|
if value := os.Getenv(key); value != "" {
|
||||||
|
boolVal, err := strconv.ParseBool(value)
|
||||||
|
if err == nil {
|
||||||
|
return boolVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEnvInt(key string, defaultValue int) int {
|
||||||
|
if value := os.Getenv(key); value != "" {
|
||||||
|
intVal, err := strconv.Atoi(value)
|
||||||
|
if err == nil {
|
||||||
|
return intVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
// RateLimiterConfig defines rate limiting configuration
|
// RateLimiterConfig defines rate limiting configuration
|
||||||
type RateLimiterConfig struct {
|
type RateLimiterConfig struct {
|
||||||
|
Enabled bool
|
||||||
RequestsPerMinute int
|
RequestsPerMinute int
|
||||||
CleanupInterval time.Duration
|
CleanupInterval time.Duration
|
||||||
}
|
}
|
||||||
@@ -17,6 +18,7 @@ type RateLimiterConfig struct {
|
|||||||
// DefaultRateLimiterConfig returns sensible defaults
|
// DefaultRateLimiterConfig returns sensible defaults
|
||||||
func DefaultRateLimiterConfig() RateLimiterConfig {
|
func DefaultRateLimiterConfig() RateLimiterConfig {
|
||||||
return RateLimiterConfig{
|
return RateLimiterConfig{
|
||||||
|
Enabled: true,
|
||||||
RequestsPerMinute: 10,
|
RequestsPerMinute: 10,
|
||||||
CleanupInterval: 5 * time.Minute,
|
CleanupInterval: 5 * time.Minute,
|
||||||
}
|
}
|
||||||
@@ -98,6 +100,11 @@ func (rl *RateLimiter) Allow(ip string) bool {
|
|||||||
func RateLimiterMiddleware(rl *RateLimiter) echo.MiddlewareFunc {
|
func RateLimiterMiddleware(rl *RateLimiter) echo.MiddlewareFunc {
|
||||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
|
// If rate limiting is disabled, skip checks
|
||||||
|
if !rl.config.Enabled {
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
|
||||||
// Get client IP
|
// Get client IP
|
||||||
ip := c.RealIP()
|
ip := c.RealIP()
|
||||||
if ip == "" {
|
if ip == "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user