164 lines
4.3 KiB
Go
164 lines
4.3 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Config struct {
|
|
Server ServerConfig
|
|
Database DatabaseConfig
|
|
JWT JWTConfig
|
|
Storage StorageConfig
|
|
Redis RedisConfig
|
|
AllowedOrigins []string
|
|
}
|
|
|
|
type ServerConfig struct {
|
|
Port string
|
|
Mode string
|
|
}
|
|
|
|
type DatabaseConfig struct {
|
|
Host string
|
|
Port string
|
|
User string
|
|
Password string
|
|
Name string
|
|
SSLMode string
|
|
MaxOpenConns int
|
|
MaxIdleConns int
|
|
ConnMaxLifetime time.Duration
|
|
ConnMaxIdleTime time.Duration
|
|
}
|
|
|
|
type JWTConfig struct {
|
|
Secret string
|
|
ExpireTime time.Duration
|
|
ExpireHours int
|
|
}
|
|
|
|
// StorageConfig S3 兼容对象存储(MinIO / OSS / COS / S3 共用字段)
|
|
type StorageConfig struct {
|
|
Endpoint string // 如 localhost:9100(开发 MinIO)或 oss-cn-hangzhou.aliyuncs.com
|
|
AccessKey string
|
|
SecretKey string
|
|
Bucket string
|
|
UseSSL bool
|
|
Region string
|
|
PublicBase string // 浏览器可访问前缀,如 http://localhost:9100/kefu
|
|
MaxUploadMB int
|
|
MaxImageEdge int // 最长边像素
|
|
WebPQuality float32
|
|
}
|
|
|
|
// RedisConfig 可选的跨节点 WebSocket 广播总线(多 API 副本部署时启用)。
|
|
type RedisConfig struct {
|
|
Addr string // 为空表示单实例模式,WS 广播仅进程内
|
|
Password string
|
|
DB int
|
|
}
|
|
|
|
func Load() *Config {
|
|
return &Config{
|
|
Server: ServerConfig{
|
|
Port: getEnv("SERVER_PORT", "8080"),
|
|
Mode: getEnv("GIN_MODE", "debug"),
|
|
},
|
|
Database: DatabaseConfig{
|
|
Host: getEnv("DB_HOST", "localhost"),
|
|
Port: getEnv("DB_PORT", "5433"),
|
|
User: getEnv("DB_USER", "postgres"),
|
|
Password: getEnv("DB_PASSWORD", "postgres"),
|
|
Name: getEnv("DB_NAME", "kefu_cloud"),
|
|
SSLMode: getEnv("DB_SSLMODE", "disable"),
|
|
MaxOpenConns: getEnvInt("DB_MAX_OPEN_CONNS", 50),
|
|
MaxIdleConns: getEnvInt("DB_MAX_IDLE_CONNS", 10),
|
|
ConnMaxLifetime: time.Duration(getEnvInt("DB_CONN_MAX_LIFETIME_MINUTES", 60)) * time.Minute,
|
|
ConnMaxIdleTime: time.Duration(getEnvInt("DB_CONN_MAX_IDLE_MINUTES", 15)) * time.Minute,
|
|
},
|
|
JWT: func() JWTConfig {
|
|
hours := getEnvInt("JWT_EXPIRE_HOURS", 24)
|
|
if hours <= 0 {
|
|
hours = 24
|
|
}
|
|
return JWTConfig{
|
|
Secret: getEnv("JWT_SECRET", "kefu-cloud-secret-key"),
|
|
ExpireTime: time.Duration(hours) * time.Hour,
|
|
ExpireHours: hours,
|
|
}
|
|
}(),
|
|
Storage: StorageConfig{
|
|
// 默认映射宿主机 9100→容器 9000,避免与其它项目 MinIO 冲突
|
|
Endpoint: getEnv("STORAGE_ENDPOINT", "localhost:9100"),
|
|
AccessKey: getEnv("STORAGE_ACCESS_KEY", "minioadmin"),
|
|
SecretKey: getEnv("STORAGE_SECRET_KEY", "minioadmin"),
|
|
Bucket: getEnv("STORAGE_BUCKET", "kefu"),
|
|
UseSSL: getEnvBool("STORAGE_USE_SSL", false),
|
|
Region: getEnv("STORAGE_REGION", "us-east-1"),
|
|
PublicBase: getEnv("STORAGE_PUBLIC_BASE_URL", "http://localhost:9100/kefu"),
|
|
MaxUploadMB: getEnvInt("STORAGE_MAX_UPLOAD_MB", 10),
|
|
MaxImageEdge: getEnvInt("STORAGE_MAX_IMAGE_EDGE", 1920),
|
|
WebPQuality: float32(getEnvInt("STORAGE_WEBP_QUALITY", 80)),
|
|
},
|
|
AllowedOrigins: splitCSV(getEnv("CORS_ALLOW_ORIGINS", "*")),
|
|
Redis: RedisConfig{
|
|
Addr: getEnv("REDIS_ADDR", ""),
|
|
Password: getEnv("REDIS_PASSWORD", ""),
|
|
DB: getEnvInt("REDIS_DB", 0),
|
|
},
|
|
}
|
|
}
|
|
|
|
func splitCSV(raw string) []string {
|
|
parts := strings.Split(raw, ",")
|
|
result := make([]string, 0, len(parts))
|
|
for _, part := range parts {
|
|
if value := strings.TrimSpace(part); value != "" {
|
|
result = append(result, value)
|
|
}
|
|
}
|
|
if len(result) == 0 {
|
|
return []string{"*"}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (d *DatabaseConfig) DSN() string {
|
|
return "host=" + d.Host + " port=" + d.Port + " user=" + d.User +
|
|
" password=" + d.Password + " dbname=" + d.Name + " sslmode=" + d.SSLMode
|
|
}
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func getEnvBool(key string, fallback bool) bool {
|
|
v := os.Getenv(key)
|
|
if v == "" {
|
|
return fallback
|
|
}
|
|
b, err := strconv.ParseBool(v)
|
|
if err != nil {
|
|
return fallback
|
|
}
|
|
return b
|
|
}
|
|
|
|
func getEnvInt(key string, fallback int) int {
|
|
v := os.Getenv(key)
|
|
if v == "" {
|
|
return fallback
|
|
}
|
|
n, err := strconv.Atoi(v)
|
|
if err != nil {
|
|
return fallback
|
|
}
|
|
return n
|
|
}
|