Files
EveryPublish/server/internal/config/config.go
T

62 lines
1.9 KiB
Go

package config
import (
"fmt"
"os"
)
// Config 服务器配置(环境变量优先,.env 兜底)
type Config struct {
ServerAddr string
MySQLDSN string
RedisAddr string
RedisPass string
JWTSecret string
BaseURL string
PublicBaseURL string // 浏览器侧访问地址(邀请链接等)
StorageDir string
StaticDir string // 前端生产构建目录(空=不托管静态)
MaxUploadBytes int64 // multipart 上传体积上限
}
// Load 从环境变量加载
func Load() *Config {
jwt := getenv("JWT_SECRET", "dev-secret-change-me")
if jwt == "dev-secret-change-me" || jwt == "please-change-me-in-production" || len(jwt) < 16 {
// 生产安全红线:默认/过短密钥可被伪造 JWT(含 admin 提权)。
// 保留 dev 默认值以便本地开发,但在任何环境都打印醒目告警。
println("!! [security] JWT_SECRET 使用默认值或长度不足(<16)。生产环境必须设置强随机 JWT_SECRET,否则任何人都能伪造令牌(admin 提权)。")
}
return &Config{
ServerAddr: getenv("SERVER_ADDR", ":8090"),
MySQLDSN: getenv("MYSQL_DSN", "root:everypublish@tcp(127.0.0.1:3306)/everypublish?charset=utf8mb4&parseTime=True&loc=Local"),
RedisAddr: getenv("REDIS_ADDR", "127.0.0.1:6379"),
RedisPass: getenv("REDIS_PASSWORD", ""),
JWTSecret: jwt,
BaseURL: getenv("BASE_URL", "http://127.0.0.1:8090"),
PublicBaseURL: getenv("PUBLIC_BASE_URL", getenv("BASE_URL", "http://127.0.0.1:8090")),
StorageDir: getenv("STORAGE_DIR", "./data/materials"),
StaticDir: getenv("STATIC_DIR", "../apps/web/dist"),
MaxUploadBytes: getenvInt64("MAX_UPLOAD_BYTES", 2<<30),
}
}
func getenvInt64(k string, def int64) int64 {
v := os.Getenv(k)
if v == "" {
return def
}
var n int64
if _, err := fmt.Sscanf(v, "%d", &n); err != nil || n <= 0 {
return def
}
return n
}
func getenv(k, def string) string {
if v := os.Getenv(k); v != "" {
return v
}
return def
}