Files
nl-pms-api/internal/config/config.go
2026-08-15 17:04:47 +08:00

95 lines
3.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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"`
// 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 {
DSN string `yaml:"dsn"`
} `yaml:"mysql"`
}
// MaxUploadBytes 返回单文件字节上限。
func (c *Config) MaxUploadBytes() int64 { return c.MaxUploadMB << 20 }
// MaxReleaseBytes 返回发版包字节上限。
func (c *Config) MaxReleaseBytes() int64 { return c.MaxReleaseMB << 20 }
// Load 读取并校验配置缺省值prod / :8788 / ./uploads / 20MB / access 2h / refresh 30d。
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
}
if c.MaxReleaseMB <= 0 {
c.MaxReleaseMB = 200
}
if c.AccessTTLHours <= 0 {
c.AccessTTLHours = 2
}
if c.RefreshTTLDays <= 0 {
c.RefreshTTLDays = 30
}
c.BaseURL = strings.TrimRight(strings.TrimSpace(c.BaseURL), "/")
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_secretJWT 签发密钥,不允许留空)")
}
if strings.TrimSpace(c.MySQL.DSN) == "" {
return nil, errors.New("配置缺少 mysql.dsn")
}
return c, nil
}