config.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Package config предоставляет конфигурацию приложения.
  2. // Загружает переменные окружения через godotenv, поддерживает Docker-секреты
  3. // через суффикс _FILE (getSecret), сборку DatabaseURL/RedisURL из компонентов.
  4. // Экспортирует структуру Config со всеми настройками (БД, S3, JWT, Redis, CORS).
  5. package config
  6. import (
  7. "os"
  8. "strings"
  9. "github.com/joho/godotenv"
  10. )
  11. type Config struct {
  12. AppEnv string
  13. ServerPort string
  14. DatabaseURL string
  15. RedisURL string
  16. S3Endpoint string
  17. S3PublicEndpoint string
  18. S3AccessKey string
  19. S3SecretKey string
  20. S3Bucket string
  21. JWTSecret string
  22. JWTRefreshSecret string
  23. // CloudPaymentsPublicID и CloudPaymentsAPISecret зарезервированы для будущей интеграции платежей
  24. CloudPaymentsPublicID string
  25. CloudPaymentsAPISecret string
  26. AllowedOrigins []string
  27. }
  28. func Load() *Config {
  29. godotenv.Load()
  30. cfg := &Config{
  31. AppEnv: getEnv("APP_ENV", "development"),
  32. ServerPort: getEnv("SERVER_PORT", "8080"),
  33. DatabaseURL: buildDatabaseURL(),
  34. RedisURL: buildRedisURL(),
  35. S3Endpoint: getEnv("S3_ENDPOINT", "http://localhost:9000"),
  36. S3PublicEndpoint: getEnv("S3_PUBLIC_ENDPOINT", "http://localhost:9000"),
  37. S3AccessKey: getEnv("S3_ACCESS_KEY", "photoplaces"),
  38. S3SecretKey: getSecret("S3_SECRET_KEY", "photoplaces_dev"),
  39. S3Bucket: getEnv("S3_BUCKET", "photoplaces"),
  40. JWTSecret: getSecret("JWT_SECRET", "dev-secret"),
  41. JWTRefreshSecret: getSecret("JWT_REFRESH_SECRET", "dev-refresh-secret"),
  42. CloudPaymentsPublicID: getEnv("CLOUDPAYMENTS_PUBLIC_ID", ""),
  43. CloudPaymentsAPISecret: getEnv("CLOUDPAYMENTS_API_SECRET", ""),
  44. AllowedOrigins: strings.Split(getEnv("ALLOWED_ORIGINS", "http://localhost:3000"), ","),
  45. }
  46. return cfg
  47. }
  48. func getEnv(key, fallback string) string {
  49. if v := os.Getenv(key); v != "" {
  50. return v
  51. }
  52. return fallback
  53. }
  54. func getSecret(key, fallback string) string {
  55. // Try _FILE variant first (Docker secrets)
  56. if v := os.Getenv(key + "_FILE"); v != "" {
  57. content, err := os.ReadFile(v)
  58. if err == nil {
  59. return strings.TrimSpace(string(content))
  60. }
  61. }
  62. // Fallback to env var
  63. if v := os.Getenv(key); v != "" {
  64. return v
  65. }
  66. return fallback
  67. }
  68. func buildDatabaseURL() string {
  69. // If DATABASE_URL is explicitly set, use it
  70. if v := os.Getenv("DATABASE_URL"); v != "" {
  71. return v
  72. }
  73. // Build from components with secret from file
  74. password := getSecret("DB_PASSWORD", "photoplaces_dev")
  75. return "postgres://photoplaces:" + password + "@postgres:5432/photoplaces?sslmode=disable"
  76. }
  77. func buildRedisURL() string {
  78. if v := os.Getenv("REDIS_URL"); v != "" {
  79. return v
  80. }
  81. password := getSecret("REDIS_PASSWORD", "")
  82. if password != "" {
  83. return "redis://:" + password + "@redis:6379/0"
  84. }
  85. return "redis://redis:6379/0"
  86. }