2025-11-28 23:30:49 +08:00
|
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"strconv"
|
2025-12-02 17:40:39 +08:00
|
|
|
|
"strings"
|
2025-11-28 23:30:49 +08:00
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/joho/godotenv"
|
|
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Config 应用配置结构体
|
|
|
|
|
|
type Config struct {
|
2025-11-30 18:56:56 +08:00
|
|
|
|
Environment string `mapstructure:"environment"`
|
2025-12-08 19:12:30 +08:00
|
|
|
|
Site SiteConfig `mapstructure:"site"`
|
2025-11-30 18:56:56 +08:00
|
|
|
|
Server ServerConfig `mapstructure:"server"`
|
|
|
|
|
|
Database DatabaseConfig `mapstructure:"database"`
|
|
|
|
|
|
Redis RedisConfig `mapstructure:"redis"`
|
|
|
|
|
|
RustFS RustFSConfig `mapstructure:"rustfs"`
|
|
|
|
|
|
JWT JWTConfig `mapstructure:"jwt"`
|
|
|
|
|
|
Casbin CasbinConfig `mapstructure:"casbin"`
|
|
|
|
|
|
Log LogConfig `mapstructure:"log"`
|
|
|
|
|
|
Email EmailConfig `mapstructure:"email"`
|
2025-12-02 17:40:39 +08:00
|
|
|
|
Security SecurityConfig `mapstructure:"security"`
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-08 19:12:30 +08:00
|
|
|
|
// SiteConfig 站点配置
|
|
|
|
|
|
type SiteConfig struct {
|
|
|
|
|
|
Name string `mapstructure:"name"`
|
|
|
|
|
|
Description string `mapstructure:"description"`
|
|
|
|
|
|
RegistrationEnabled bool `mapstructure:"registration_enabled"`
|
|
|
|
|
|
DefaultAvatar string `mapstructure:"default_avatar"`
|
|
|
|
|
|
MaxTexturesPerUser int `mapstructure:"max_textures_per_user"`
|
|
|
|
|
|
MaxProfilesPerUser int `mapstructure:"max_profiles_per_user"`
|
|
|
|
|
|
CheckinReward int `mapstructure:"checkin_reward"`
|
|
|
|
|
|
TextureDownloadReward int `mapstructure:"texture_download_reward"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// ServerConfig 服务器配置
|
|
|
|
|
|
type ServerConfig struct {
|
|
|
|
|
|
Port string `mapstructure:"port"`
|
|
|
|
|
|
Mode string `mapstructure:"mode"`
|
|
|
|
|
|
ReadTimeout time.Duration `mapstructure:"read_timeout"`
|
|
|
|
|
|
WriteTimeout time.Duration `mapstructure:"write_timeout"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// DatabaseConfig 数据库配置
|
|
|
|
|
|
type DatabaseConfig struct {
|
|
|
|
|
|
Driver string `mapstructure:"driver"`
|
|
|
|
|
|
Host string `mapstructure:"host"`
|
|
|
|
|
|
Port int `mapstructure:"port"`
|
|
|
|
|
|
Username string `mapstructure:"username"`
|
|
|
|
|
|
Password string `mapstructure:"password"`
|
|
|
|
|
|
Database string `mapstructure:"database"`
|
|
|
|
|
|
SSLMode string `mapstructure:"ssl_mode"`
|
|
|
|
|
|
Timezone string `mapstructure:"timezone"`
|
|
|
|
|
|
MaxIdleConns int `mapstructure:"max_idle_conns"`
|
|
|
|
|
|
MaxOpenConns int `mapstructure:"max_open_conns"`
|
|
|
|
|
|
ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime"`
|
2025-12-03 10:58:39 +08:00
|
|
|
|
ConnMaxIdleTime time.Duration `mapstructure:"conn_max_idle_time"` // 连接最大空闲时间
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RedisConfig Redis配置
|
|
|
|
|
|
type RedisConfig struct {
|
2025-12-03 10:58:39 +08:00
|
|
|
|
Host string `mapstructure:"host"`
|
|
|
|
|
|
Port int `mapstructure:"port"`
|
|
|
|
|
|
Password string `mapstructure:"password"`
|
|
|
|
|
|
Database int `mapstructure:"database"`
|
|
|
|
|
|
PoolSize int `mapstructure:"pool_size"` // 连接池大小
|
|
|
|
|
|
MinIdleConns int `mapstructure:"min_idle_conns"` // 最小空闲连接数
|
|
|
|
|
|
MaxRetries int `mapstructure:"max_retries"` // 最大重试次数
|
|
|
|
|
|
DialTimeout time.Duration `mapstructure:"dial_timeout"` // 连接超时
|
|
|
|
|
|
ReadTimeout time.Duration `mapstructure:"read_timeout"` // 读取超时
|
|
|
|
|
|
WriteTimeout time.Duration `mapstructure:"write_timeout"` // 写入超时
|
|
|
|
|
|
PoolTimeout time.Duration `mapstructure:"pool_timeout"` // 连接池超时
|
|
|
|
|
|
ConnMaxIdleTime time.Duration `mapstructure:"conn_max_idle_time"` // 连接最大空闲时间
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// RustFSConfig RustFS对象存储配置 (S3兼容)
|
|
|
|
|
|
type RustFSConfig struct {
|
|
|
|
|
|
Endpoint string `mapstructure:"endpoint"`
|
2025-12-02 11:22:14 +08:00
|
|
|
|
PublicURL string `mapstructure:"public_url"` // 公开访问URL (用于生成文件访问链接)
|
2025-11-28 23:30:49 +08:00
|
|
|
|
AccessKey string `mapstructure:"access_key"`
|
|
|
|
|
|
SecretKey string `mapstructure:"secret_key"`
|
|
|
|
|
|
UseSSL bool `mapstructure:"use_ssl"`
|
|
|
|
|
|
Buckets map[string]string `mapstructure:"buckets"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// JWTConfig JWT配置
|
|
|
|
|
|
type JWTConfig struct {
|
|
|
|
|
|
Secret string `mapstructure:"secret"`
|
|
|
|
|
|
ExpireHours int `mapstructure:"expire_hours"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CasbinConfig Casbin权限配置
|
|
|
|
|
|
type CasbinConfig struct {
|
|
|
|
|
|
ModelPath string `mapstructure:"model_path"`
|
|
|
|
|
|
PolicyAdapter string `mapstructure:"policy_adapter"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// LogConfig 日志配置
|
|
|
|
|
|
type LogConfig struct {
|
2025-11-30 18:56:56 +08:00
|
|
|
|
Level string `mapstructure:"level"`
|
|
|
|
|
|
Format string `mapstructure:"format"`
|
|
|
|
|
|
Output string `mapstructure:"output"`
|
|
|
|
|
|
MaxSize int `mapstructure:"max_size"`
|
|
|
|
|
|
MaxBackups int `mapstructure:"max_backups"`
|
|
|
|
|
|
MaxAge int `mapstructure:"max_age"`
|
|
|
|
|
|
Compress bool `mapstructure:"compress"`
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// EmailConfig 邮件配置
|
|
|
|
|
|
type EmailConfig struct {
|
|
|
|
|
|
Enabled bool `mapstructure:"enabled"`
|
|
|
|
|
|
SMTPHost string `mapstructure:"smtp_host"`
|
|
|
|
|
|
SMTPPort int `mapstructure:"smtp_port"`
|
|
|
|
|
|
Username string `mapstructure:"username"`
|
|
|
|
|
|
Password string `mapstructure:"password"`
|
|
|
|
|
|
FromName string `mapstructure:"from_name"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-02 17:40:39 +08:00
|
|
|
|
// SecurityConfig 安全配置
|
|
|
|
|
|
type SecurityConfig struct {
|
|
|
|
|
|
AllowedOrigins []string `mapstructure:"allowed_origins"` // 允许的CORS来源
|
|
|
|
|
|
AllowedDomains []string `mapstructure:"allowed_domains"` // 允许的头像/材质URL域名
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// Load 加载配置 - 完全从环境变量加载,不依赖YAML文件
|
|
|
|
|
|
func Load() (*Config, error) {
|
|
|
|
|
|
// 加载.env文件(如果存在)
|
|
|
|
|
|
_ = godotenv.Load(".env")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 设置默认值
|
|
|
|
|
|
setDefaults()
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 设置环境变量前缀
|
|
|
|
|
|
viper.SetEnvPrefix("CARROTSKIN")
|
|
|
|
|
|
viper.AutomaticEnv()
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 手动设置环境变量映射
|
|
|
|
|
|
setupEnvMappings()
|
|
|
|
|
|
|
|
|
|
|
|
// 直接从环境变量解析配置
|
|
|
|
|
|
var config Config
|
|
|
|
|
|
if err := viper.Unmarshal(&config); err != nil {
|
|
|
|
|
|
return nil, fmt.Errorf("解析配置失败: %w", err)
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 从环境变量中覆盖配置
|
|
|
|
|
|
overrideFromEnv(&config)
|
|
|
|
|
|
|
|
|
|
|
|
return &config, nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setDefaults 设置默认配置值
|
|
|
|
|
|
func setDefaults() {
|
|
|
|
|
|
// 服务器默认配置
|
|
|
|
|
|
viper.SetDefault("server.port", ":8080")
|
|
|
|
|
|
viper.SetDefault("server.mode", "debug")
|
|
|
|
|
|
viper.SetDefault("server.read_timeout", "30s")
|
|
|
|
|
|
viper.SetDefault("server.write_timeout", "30s")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 数据库默认配置
|
|
|
|
|
|
viper.SetDefault("database.driver", "postgres")
|
|
|
|
|
|
viper.SetDefault("database.host", "localhost")
|
|
|
|
|
|
viper.SetDefault("database.port", 5432)
|
|
|
|
|
|
viper.SetDefault("database.ssl_mode", "disable")
|
|
|
|
|
|
viper.SetDefault("database.timezone", "Asia/Shanghai")
|
|
|
|
|
|
viper.SetDefault("database.max_idle_conns", 10)
|
|
|
|
|
|
viper.SetDefault("database.max_open_conns", 100)
|
|
|
|
|
|
viper.SetDefault("database.conn_max_lifetime", "1h")
|
2025-12-03 10:58:39 +08:00
|
|
|
|
viper.SetDefault("database.conn_max_idle_time", "10m")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// Redis默认配置
|
|
|
|
|
|
viper.SetDefault("redis.host", "localhost")
|
|
|
|
|
|
viper.SetDefault("redis.port", 6379)
|
|
|
|
|
|
viper.SetDefault("redis.database", 0)
|
|
|
|
|
|
viper.SetDefault("redis.pool_size", 10)
|
2025-12-03 10:58:39 +08:00
|
|
|
|
viper.SetDefault("redis.min_idle_conns", 5)
|
|
|
|
|
|
viper.SetDefault("redis.max_retries", 3)
|
|
|
|
|
|
viper.SetDefault("redis.dial_timeout", "5s")
|
|
|
|
|
|
viper.SetDefault("redis.read_timeout", "3s")
|
|
|
|
|
|
viper.SetDefault("redis.write_timeout", "3s")
|
|
|
|
|
|
viper.SetDefault("redis.pool_timeout", "4s")
|
|
|
|
|
|
viper.SetDefault("redis.conn_max_idle_time", "30m")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// RustFS默认配置
|
|
|
|
|
|
viper.SetDefault("rustfs.endpoint", "127.0.0.1:9000")
|
2025-12-02 17:40:39 +08:00
|
|
|
|
viper.SetDefault("rustfs.public_url", "") // 为空时使用 endpoint 构建 URL
|
2025-11-28 23:30:49 +08:00
|
|
|
|
viper.SetDefault("rustfs.use_ssl", false)
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// JWT默认配置
|
|
|
|
|
|
viper.SetDefault("jwt.expire_hours", 168)
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// Casbin默认配置
|
|
|
|
|
|
viper.SetDefault("casbin.model_path", "configs/casbin/rbac_model.conf")
|
|
|
|
|
|
viper.SetDefault("casbin.policy_adapter", "gorm")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 日志默认配置
|
|
|
|
|
|
viper.SetDefault("log.level", "info")
|
|
|
|
|
|
viper.SetDefault("log.format", "json")
|
|
|
|
|
|
viper.SetDefault("log.output", "logs/app.log")
|
|
|
|
|
|
viper.SetDefault("log.max_size", 100)
|
|
|
|
|
|
viper.SetDefault("log.max_backups", 3)
|
|
|
|
|
|
viper.SetDefault("log.max_age", 28)
|
|
|
|
|
|
viper.SetDefault("log.compress", true)
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 邮件默认配置
|
|
|
|
|
|
viper.SetDefault("email.enabled", false)
|
|
|
|
|
|
viper.SetDefault("email.smtp_port", 587)
|
2025-12-02 17:40:39 +08:00
|
|
|
|
|
|
|
|
|
|
// 安全默认配置
|
|
|
|
|
|
viper.SetDefault("security.allowed_origins", []string{"*"})
|
|
|
|
|
|
viper.SetDefault("security.allowed_domains", []string{"localhost", "127.0.0.1"})
|
2025-12-08 19:12:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 站点默认配置
|
|
|
|
|
|
viper.SetDefault("site.name", "CarrotSkin")
|
|
|
|
|
|
viper.SetDefault("site.description", "一个优秀的Minecraft皮肤站")
|
|
|
|
|
|
viper.SetDefault("site.registration_enabled", true)
|
|
|
|
|
|
viper.SetDefault("site.default_avatar", "")
|
|
|
|
|
|
viper.SetDefault("site.max_textures_per_user", 50)
|
|
|
|
|
|
viper.SetDefault("site.max_profiles_per_user", 5)
|
|
|
|
|
|
viper.SetDefault("site.checkin_reward", 10)
|
|
|
|
|
|
viper.SetDefault("site.texture_download_reward", 1)
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// setupEnvMappings 设置环境变量映射
|
|
|
|
|
|
func setupEnvMappings() {
|
|
|
|
|
|
// 服务器配置
|
|
|
|
|
|
viper.BindEnv("server.port", "SERVER_PORT")
|
|
|
|
|
|
viper.BindEnv("server.mode", "SERVER_MODE")
|
|
|
|
|
|
viper.BindEnv("server.read_timeout", "SERVER_READ_TIMEOUT")
|
|
|
|
|
|
viper.BindEnv("server.write_timeout", "SERVER_WRITE_TIMEOUT")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 数据库配置
|
|
|
|
|
|
viper.BindEnv("database.driver", "DATABASE_DRIVER")
|
|
|
|
|
|
viper.BindEnv("database.host", "DATABASE_HOST")
|
|
|
|
|
|
viper.BindEnv("database.port", "DATABASE_PORT")
|
|
|
|
|
|
viper.BindEnv("database.username", "DATABASE_USERNAME")
|
|
|
|
|
|
viper.BindEnv("database.password", "DATABASE_PASSWORD")
|
|
|
|
|
|
viper.BindEnv("database.database", "DATABASE_NAME")
|
|
|
|
|
|
viper.BindEnv("database.ssl_mode", "DATABASE_SSL_MODE")
|
|
|
|
|
|
viper.BindEnv("database.timezone", "DATABASE_TIMEZONE")
|
2025-12-03 10:58:39 +08:00
|
|
|
|
viper.BindEnv("database.max_idle_conns", "DATABASE_MAX_IDLE_CONNS")
|
|
|
|
|
|
viper.BindEnv("database.max_open_conns", "DATABASE_MAX_OPEN_CONNS")
|
|
|
|
|
|
viper.BindEnv("database.conn_max_lifetime", "DATABASE_CONN_MAX_LIFETIME")
|
|
|
|
|
|
viper.BindEnv("database.conn_max_idle_time", "DATABASE_CONN_MAX_IDLE_TIME")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// Redis配置
|
|
|
|
|
|
viper.BindEnv("redis.host", "REDIS_HOST")
|
|
|
|
|
|
viper.BindEnv("redis.port", "REDIS_PORT")
|
|
|
|
|
|
viper.BindEnv("redis.password", "REDIS_PASSWORD")
|
|
|
|
|
|
viper.BindEnv("redis.database", "REDIS_DATABASE")
|
2025-12-03 10:58:39 +08:00
|
|
|
|
viper.BindEnv("redis.pool_size", "REDIS_POOL_SIZE")
|
|
|
|
|
|
viper.BindEnv("redis.min_idle_conns", "REDIS_MIN_IDLE_CONNS")
|
|
|
|
|
|
viper.BindEnv("redis.max_retries", "REDIS_MAX_RETRIES")
|
|
|
|
|
|
viper.BindEnv("redis.dial_timeout", "REDIS_DIAL_TIMEOUT")
|
|
|
|
|
|
viper.BindEnv("redis.read_timeout", "REDIS_READ_TIMEOUT")
|
|
|
|
|
|
viper.BindEnv("redis.write_timeout", "REDIS_WRITE_TIMEOUT")
|
|
|
|
|
|
viper.BindEnv("redis.pool_timeout", "REDIS_POOL_TIMEOUT")
|
|
|
|
|
|
viper.BindEnv("redis.conn_max_idle_time", "REDIS_CONN_MAX_IDLE_TIME")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// RustFS配置
|
|
|
|
|
|
viper.BindEnv("rustfs.endpoint", "RUSTFS_ENDPOINT")
|
2025-12-02 11:22:14 +08:00
|
|
|
|
viper.BindEnv("rustfs.public_url", "RUSTFS_PUBLIC_URL")
|
2025-11-28 23:30:49 +08:00
|
|
|
|
viper.BindEnv("rustfs.access_key", "RUSTFS_ACCESS_KEY")
|
|
|
|
|
|
viper.BindEnv("rustfs.secret_key", "RUSTFS_SECRET_KEY")
|
|
|
|
|
|
viper.BindEnv("rustfs.use_ssl", "RUSTFS_USE_SSL")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// JWT配置
|
|
|
|
|
|
viper.BindEnv("jwt.secret", "JWT_SECRET")
|
|
|
|
|
|
viper.BindEnv("jwt.expire_hours", "JWT_EXPIRE_HOURS")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 日志配置
|
|
|
|
|
|
viper.BindEnv("log.level", "LOG_LEVEL")
|
|
|
|
|
|
viper.BindEnv("log.format", "LOG_FORMAT")
|
|
|
|
|
|
viper.BindEnv("log.output", "LOG_OUTPUT")
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 邮件配置
|
|
|
|
|
|
viper.BindEnv("email.enabled", "EMAIL_ENABLED")
|
|
|
|
|
|
viper.BindEnv("email.smtp_host", "EMAIL_SMTP_HOST")
|
|
|
|
|
|
viper.BindEnv("email.smtp_port", "EMAIL_SMTP_PORT")
|
|
|
|
|
|
viper.BindEnv("email.username", "EMAIL_USERNAME")
|
|
|
|
|
|
viper.BindEnv("email.password", "EMAIL_PASSWORD")
|
|
|
|
|
|
viper.BindEnv("email.from_name", "EMAIL_FROM_NAME")
|
2025-12-08 19:12:30 +08:00
|
|
|
|
|
|
|
|
|
|
// 站点配置
|
|
|
|
|
|
viper.BindEnv("site.name", "SITE_NAME")
|
|
|
|
|
|
viper.BindEnv("site.description", "SITE_DESCRIPTION")
|
|
|
|
|
|
viper.BindEnv("site.registration_enabled", "REGISTRATION_ENABLED")
|
|
|
|
|
|
viper.BindEnv("site.default_avatar", "DEFAULT_AVATAR")
|
|
|
|
|
|
viper.BindEnv("site.max_textures_per_user", "MAX_TEXTURES_PER_USER")
|
|
|
|
|
|
viper.BindEnv("site.max_profiles_per_user", "MAX_PROFILES_PER_USER")
|
|
|
|
|
|
viper.BindEnv("site.checkin_reward", "CHECKIN_REWARD")
|
|
|
|
|
|
viper.BindEnv("site.texture_download_reward", "TEXTURE_DOWNLOAD_REWARD")
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// overrideFromEnv 从环境变量中覆盖配置
|
|
|
|
|
|
func overrideFromEnv(config *Config) {
|
|
|
|
|
|
// 处理RustFS存储桶配置
|
|
|
|
|
|
if texturesBucket := os.Getenv("RUSTFS_BUCKET_TEXTURES"); texturesBucket != "" {
|
|
|
|
|
|
if config.RustFS.Buckets == nil {
|
|
|
|
|
|
config.RustFS.Buckets = make(map[string]string)
|
|
|
|
|
|
}
|
|
|
|
|
|
config.RustFS.Buckets["textures"] = texturesBucket
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
if avatarsBucket := os.Getenv("RUSTFS_BUCKET_AVATARS"); avatarsBucket != "" {
|
|
|
|
|
|
if config.RustFS.Buckets == nil {
|
|
|
|
|
|
config.RustFS.Buckets = make(map[string]string)
|
|
|
|
|
|
}
|
|
|
|
|
|
config.RustFS.Buckets["avatars"] = avatarsBucket
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 处理数据库连接池配置
|
|
|
|
|
|
if maxIdleConns := os.Getenv("DATABASE_MAX_IDLE_CONNS"); maxIdleConns != "" {
|
|
|
|
|
|
if val, err := strconv.Atoi(maxIdleConns); err == nil {
|
|
|
|
|
|
config.Database.MaxIdleConns = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
if maxOpenConns := os.Getenv("DATABASE_MAX_OPEN_CONNS"); maxOpenConns != "" {
|
|
|
|
|
|
if val, err := strconv.Atoi(maxOpenConns); err == nil {
|
|
|
|
|
|
config.Database.MaxOpenConns = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
if connMaxLifetime := os.Getenv("DATABASE_CONN_MAX_LIFETIME"); connMaxLifetime != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(connMaxLifetime); err == nil {
|
|
|
|
|
|
config.Database.ConnMaxLifetime = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-12-03 10:58:39 +08:00
|
|
|
|
if connMaxIdleTime := os.Getenv("DATABASE_CONN_MAX_IDLE_TIME"); connMaxIdleTime != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(connMaxIdleTime); err == nil {
|
|
|
|
|
|
config.Database.ConnMaxIdleTime = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理Redis连接池配置
|
2025-11-28 23:30:49 +08:00
|
|
|
|
if poolSize := os.Getenv("REDIS_POOL_SIZE"); poolSize != "" {
|
|
|
|
|
|
if val, err := strconv.Atoi(poolSize); err == nil {
|
|
|
|
|
|
config.Redis.PoolSize = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
2025-12-03 10:58:39 +08:00
|
|
|
|
if minIdleConns := os.Getenv("REDIS_MIN_IDLE_CONNS"); minIdleConns != "" {
|
|
|
|
|
|
if val, err := strconv.Atoi(minIdleConns); err == nil {
|
|
|
|
|
|
config.Redis.MinIdleConns = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if maxRetries := os.Getenv("REDIS_MAX_RETRIES"); maxRetries != "" {
|
|
|
|
|
|
if val, err := strconv.Atoi(maxRetries); err == nil {
|
|
|
|
|
|
config.Redis.MaxRetries = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if dialTimeout := os.Getenv("REDIS_DIAL_TIMEOUT"); dialTimeout != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(dialTimeout); err == nil {
|
|
|
|
|
|
config.Redis.DialTimeout = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if readTimeout := os.Getenv("REDIS_READ_TIMEOUT"); readTimeout != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(readTimeout); err == nil {
|
|
|
|
|
|
config.Redis.ReadTimeout = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if writeTimeout := os.Getenv("REDIS_WRITE_TIMEOUT"); writeTimeout != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(writeTimeout); err == nil {
|
|
|
|
|
|
config.Redis.WriteTimeout = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if poolTimeout := os.Getenv("REDIS_POOL_TIMEOUT"); poolTimeout != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(poolTimeout); err == nil {
|
|
|
|
|
|
config.Redis.PoolTimeout = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if connMaxIdleTime := os.Getenv("REDIS_CONN_MAX_IDLE_TIME"); connMaxIdleTime != "" {
|
|
|
|
|
|
if val, err := time.ParseDuration(connMaxIdleTime); err == nil {
|
|
|
|
|
|
config.Redis.ConnMaxIdleTime = val
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-28 23:30:49 +08:00
|
|
|
|
// 处理邮件配置
|
|
|
|
|
|
if emailEnabled := os.Getenv("EMAIL_ENABLED"); emailEnabled != "" {
|
|
|
|
|
|
config.Email.Enabled = emailEnabled == "true" || emailEnabled == "True" || emailEnabled == "TRUE" || emailEnabled == "1"
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
|
|
|
|
|
|
// 处理环境配置
|
|
|
|
|
|
if env := os.Getenv("ENVIRONMENT"); env != "" {
|
|
|
|
|
|
config.Environment = env
|
|
|
|
|
|
}
|
2025-12-02 17:40:39 +08:00
|
|
|
|
|
|
|
|
|
|
// 处理安全配置
|
|
|
|
|
|
if allowedOrigins := os.Getenv("SECURITY_ALLOWED_ORIGINS"); allowedOrigins != "" {
|
|
|
|
|
|
config.Security.AllowedOrigins = strings.Split(allowedOrigins, ",")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if allowedDomains := os.Getenv("SECURITY_ALLOWED_DOMAINS"); allowedDomains != "" {
|
|
|
|
|
|
config.Security.AllowedDomains = strings.Split(allowedDomains, ",")
|
|
|
|
|
|
}
|
2025-11-30 18:56:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// IsTestEnvironment 判断是否为测试环境
|
|
|
|
|
|
func (c *Config) IsTestEnvironment() bool {
|
|
|
|
|
|
return c.Environment == "test"
|
2025-11-28 23:30:49 +08:00
|
|
|
|
}
|