167 lines
3.8 KiB
Go
167 lines
3.8 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// ConfigProvider defines the interface for configuration operations
|
|
type ConfigProvider interface {
|
|
GetString(key string) string
|
|
GetInt(key string) int
|
|
GetBool(key string) bool
|
|
GetDuration(key string) time.Duration
|
|
IsSet(key string) bool
|
|
Validate() error
|
|
GetDatabaseDSN() string
|
|
GetDatabaseDSNForLogging() string
|
|
GetServerAddress() string
|
|
IsProduction() bool
|
|
}
|
|
|
|
// Config implements the ConfigProvider interface
|
|
type Config struct {
|
|
defaults map[string]string
|
|
}
|
|
|
|
// NewConfig creates a new configuration instance
|
|
func NewConfig() ConfigProvider {
|
|
// Load .env file if it exists
|
|
_ = godotenv.Load()
|
|
|
|
return &Config{
|
|
defaults: map[string]string{
|
|
"SERVER_HOST": "0.0.0.0",
|
|
"SERVER_PORT": "8090",
|
|
"SERVER_READ_TIMEOUT": "30s",
|
|
"SERVER_WRITE_TIMEOUT": "30s",
|
|
"SERVER_IDLE_TIMEOUT": "60s",
|
|
"DB_HOST": "localhost",
|
|
"DB_PORT": "5432",
|
|
"DB_NAME": "users",
|
|
"DB_USER": "postgres",
|
|
"DB_PASSWORD": "postgres",
|
|
"DB_SSLMODE": "disable",
|
|
"DB_MAX_OPEN_CONNS": "25",
|
|
"DB_MAX_IDLE_CONNS": "5",
|
|
"DB_CONN_MAX_LIFETIME": "5m",
|
|
"APP_ENV": "development",
|
|
"APP_VERSION": "1.0.0",
|
|
"LOG_LEVEL": "debug",
|
|
"RATE_LIMIT_ENABLED": "true",
|
|
"RATE_LIMIT_RPS": "100",
|
|
"RATE_LIMIT_BURST": "200",
|
|
"AUTH_PROVIDER": "header",
|
|
"AUTH_HEADER_USER_EMAIL": "X-User-Email",
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *Config) GetString(key string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return c.defaults[key]
|
|
}
|
|
|
|
func (c *Config) GetInt(key string) int {
|
|
value := c.GetString(key)
|
|
if value == "" {
|
|
return 0
|
|
}
|
|
|
|
intVal, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return intVal
|
|
}
|
|
|
|
func (c *Config) GetBool(key string) bool {
|
|
value := strings.ToLower(c.GetString(key))
|
|
return value == "true" || value == "1"
|
|
}
|
|
|
|
func (c *Config) GetDuration(key string) time.Duration {
|
|
value := c.GetString(key)
|
|
if value == "" {
|
|
return 0
|
|
}
|
|
|
|
duration, err := time.ParseDuration(value)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return duration
|
|
}
|
|
|
|
func (c *Config) IsSet(key string) bool {
|
|
return os.Getenv(key) != "" || c.defaults[key] != ""
|
|
}
|
|
|
|
func (c *Config) Validate() error {
|
|
required := []string{
|
|
"SERVER_HOST",
|
|
"SERVER_PORT",
|
|
"DB_HOST",
|
|
"DB_PORT",
|
|
"DB_NAME",
|
|
"DB_USER",
|
|
"DB_PASSWORD",
|
|
}
|
|
|
|
var missing []string
|
|
for _, key := range required {
|
|
if c.GetString(key) == "" {
|
|
missing = append(missing, key)
|
|
}
|
|
}
|
|
|
|
if len(missing) > 0 {
|
|
return fmt.Errorf("missing required configuration keys: %s", strings.Join(missing, ", "))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Config) GetDatabaseDSN() string {
|
|
host := c.GetString("DB_HOST")
|
|
port := c.GetString("DB_PORT")
|
|
user := c.GetString("DB_USER")
|
|
password := c.GetString("DB_PASSWORD")
|
|
dbname := c.GetString("DB_NAME")
|
|
sslmode := c.GetString("DB_SSLMODE")
|
|
|
|
// Debug logging to see what values we're getting
|
|
// fmt.Printf("DEBUG DSN VALUES: host=%s port=%s user=%s password=%s dbname=%s sslmode=%s\n",
|
|
// host, port, user, password, dbname, sslmode)
|
|
|
|
dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=%s",
|
|
host, port, user, password, dbname, sslmode)
|
|
|
|
return dsn
|
|
}
|
|
|
|
func (c *Config) GetDatabaseDSNForLogging() string {
|
|
return fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=%s",
|
|
c.GetString("DB_HOST"),
|
|
c.GetString("DB_PORT"),
|
|
c.GetString("DB_USER"),
|
|
c.GetString("DB_NAME"),
|
|
c.GetString("DB_SSLMODE"),
|
|
)
|
|
}
|
|
|
|
func (c *Config) GetServerAddress() string {
|
|
return fmt.Sprintf("%s:%s", c.GetString("SERVER_HOST"), c.GetString("SERVER_PORT"))
|
|
}
|
|
|
|
func (c *Config) IsProduction() bool {
|
|
return strings.ToLower(c.GetString("APP_ENV")) == "production"
|
|
}
|