Files

95 lines
3.0 KiB
Go
Raw Permalink Normal View History

2026-08-15 07:41:11 +08:00
package config
import (
"errors"
"fmt"
"os"
"strings"
"gopkg.in/yaml.v3"
)
// Config 是服务的全部运行配置,来自 YAML 文件(默认 ./config.yaml,可用 -config 指定)。
type Config struct {
// Env 为 dev 时启动执行 AutoMigrate;其余一律视为 prod,绝不执行 DDL。
Env string `yaml:"env"`
Listen string `yaml:"listen"`
// BaseURL 拼接文件访问 URL 的前缀(客户端可达的地址);留空则按请求 Host 推断。
BaseURL string `yaml:"base_url"`
2026-08-15 17:04:47 +08:00
// BasePath 反代保留的 URL 前缀(如 /pms-api)。1Panel 等不剥前缀时必填;留空挂在根路径。
BasePath string `yaml:"base_path"`
// JWTSecret 签发/校验 access、refresh token 的密钥,不允许留空。
JWTSecret string `yaml:"jwt_secret"`
// AccessTTLHours access token 有效小时数,默认 2。
AccessTTLHours int `yaml:"access_ttl_hours"`
// RefreshTTLDays refresh token 有效天数,默认 30。
RefreshTTLDays int `yaml:"refresh_ttl_days"`
StorageDir string `yaml:"storage_dir"`
MaxUploadMB int64 `yaml:"max_upload_mb"`
// MaxReleaseMB 发版安装包上传上限(MB),默认 200。
MaxReleaseMB int64 `yaml:"max_release_mb"`
// TrustedProxies 可信反代 CIDR/IP,用于正确解析 ClientIP;空则不信任 X-Forwarded-For。
TrustedProxies []string `yaml:"trusted_proxies"`
MySQL struct {
2026-08-15 07:41:11 +08:00
DSN string `yaml:"dsn"`
} `yaml:"mysql"`
}
// MaxUploadBytes 返回单文件字节上限。
func (c *Config) MaxUploadBytes() int64 { return c.MaxUploadMB << 20 }
2026-08-15 17:04:47 +08:00
// MaxReleaseBytes 返回发版包字节上限。
func (c *Config) MaxReleaseBytes() int64 { return c.MaxReleaseMB << 20 }
// Load 读取并校验配置,缺省值:prod / :8788 / ./uploads / 20MB / access 2h / refresh 30d。
2026-08-15 07:41:11 +08:00
func Load(path string) (*Config, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("读取配置失败: %w", err)
}
c := &Config{}
if err := yaml.Unmarshal(b, c); err != nil {
return nil, fmt.Errorf("解析配置失败: %w", err)
}
if c.Env != "dev" {
c.Env = "prod"
}
if strings.TrimSpace(c.Listen) == "" {
c.Listen = ":8788"
}
if strings.TrimSpace(c.StorageDir) == "" {
c.StorageDir = "./uploads"
}
if c.MaxUploadMB <= 0 {
c.MaxUploadMB = 20
}
2026-08-15 17:04:47 +08:00
if c.MaxReleaseMB <= 0 {
c.MaxReleaseMB = 200
}
if c.AccessTTLHours <= 0 {
c.AccessTTLHours = 2
}
if c.RefreshTTLDays <= 0 {
c.RefreshTTLDays = 30
}
2026-08-15 07:41:11 +08:00
c.BaseURL = strings.TrimRight(strings.TrimSpace(c.BaseURL), "/")
2026-08-15 17:04:47 +08:00
c.BasePath = strings.TrimSpace(c.BasePath)
if c.BasePath != "" {
if !strings.HasPrefix(c.BasePath, "/") {
c.BasePath = "/" + c.BasePath
}
c.BasePath = strings.TrimRight(c.BasePath, "/")
if c.BasePath == "/" {
c.BasePath = ""
}
}
c.JWTSecret = strings.TrimSpace(c.JWTSecret)
if c.JWTSecret == "" {
return nil, errors.New("配置缺少 jwt_secret(JWT 签发密钥,不允许留空)")
2026-08-15 07:41:11 +08:00
}
if strings.TrimSpace(c.MySQL.DSN) == "" {
return nil, errors.New("配置缺少 mysql.dsn")
}
return c, nil
}