package config import ( "flag" "fmt" "os" "strconv" "strings" "time" ) // Config contém todas as configurações da aplicação type Config struct { Server ServerConfig Auth AuthConfig Logging LoggingConfig Security SecurityConfig } // ServerConfig contém configurações do servidor HTTP type ServerConfig struct { Port string ReadTimeout time.Duration WriteTimeout time.Duration ShutdownTimeout time.Duration TLSEnabled bool TLSCertFile string TLSKeyFile string } // AuthConfig contém configurações de autenticação type AuthConfig struct { Enabled bool Username string Password string } // LoggingConfig contém configurações de logging type LoggingConfig struct { Level string // debug, info, warn, error Format string // json ou console } // SecurityConfig contém configurações de segurança type SecurityConfig struct { RateLimitEnabled bool RateLimitRPS int CORSOrigins []string } // Load carrega a configuração de múltiplas fontes (flags, env vars) func Load() (*Config, error) { cfg := &Config{} // Definir flags (mantém compatibilidade com versão anterior) flag.StringVar(&cfg.Server.Port, "port", getEnv("PORT", ":8080"), "Porta para o servidor web (ex: :8080, 9090)") flag.StringVar(&cfg.Auth.Username, "username", getEnv("USERNAME", "admin"), "Nome de usuário para autenticação") flag.StringVar(&cfg.Auth.Password, "password", getEnv("PASSWORD", ""), "Senha para autenticação") flag.Parse() // Carregar configurações de variáveis de ambiente cfg.Logging.Level = getEnv("LOG_LEVEL", "info") cfg.Logging.Format = getEnv("LOG_FORMAT", "console") cfg.Security.RateLimitEnabled = getEnvBool("RATE_LIMIT_ENABLED", true) cfg.Security.RateLimitRPS = getEnvInt("RATE_LIMIT_RPS", 100) corsOrigins := getEnv("CORS_ORIGINS", "") if corsOrigins != "" { cfg.Security.CORSOrigins = strings.Split(corsOrigins, ",") } else { cfg.Security.CORSOrigins = []string{"*"} } cfg.Server.ReadTimeout = getEnvDuration("READ_TIMEOUT", 15*time.Second) cfg.Server.WriteTimeout = getEnvDuration("WRITE_TIMEOUT", 15*time.Second) cfg.Server.ShutdownTimeout = getEnvDuration("SHUTDOWN_TIMEOUT", 30*time.Second) cfg.Server.TLSEnabled = getEnvBool("TLS_ENABLED", false) cfg.Server.TLSCertFile = getEnv("TLS_CERT_FILE", "") cfg.Server.TLSKeyFile = getEnv("TLS_KEY_FILE", "") // Autenticação está habilitada se houver senha cfg.Auth.Enabled = cfg.Auth.Password != "" // Validar configuração if err := cfg.Validate(); err != nil { return nil, err } return cfg, nil } // Validate valida a configuração func (c *Config) Validate() error { // Validar porta if c.Server.Port == "" { return fmt.Errorf("porta do servidor não pode ser vazia") } // Validar TLS if c.Server.TLSEnabled { if c.Server.TLSCertFile == "" || c.Server.TLSKeyFile == "" { return fmt.Errorf("TLS habilitado mas certificado ou chave não especificados") } } // Validar log level validLevels := map[string]bool{"debug": true, "info": true, "warn": true, "error": true} if !validLevels[c.Logging.Level] { return fmt.Errorf("nível de log inválido: %s (use: debug, info, warn, error)", c.Logging.Level) } // Validar log format if c.Logging.Format != "json" && c.Logging.Format != "console" { return fmt.Errorf("formato de log inválido: %s (use: json, console)", c.Logging.Format) } return nil } // Funções auxiliares para ler variáveis de ambiente func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue } func getEnvBool(key string, defaultValue bool) bool { if value := os.Getenv(key); value != "" { b, err := strconv.ParseBool(value) if err == nil { return b } } return defaultValue } func getEnvInt(key string, defaultValue int) int { if value := os.Getenv(key); value != "" { i, err := strconv.Atoi(value) if err == nil { return i } } return defaultValue } func getEnvDuration(key string, defaultValue time.Duration) time.Duration { if value := os.Getenv(key); value != "" { d, err := time.ParseDuration(value) if err == nil { return d } } return defaultValue }