Initial commit
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Config 全局配置结构
|
||||
type Config struct {
|
||||
App AppConfig `mapstructure:"app"`
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
JWT JWTConfig `mapstructure:"jwt"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
Encryption EncryptionConfig `mapstructure:"encryption"`
|
||||
WireGuard WireGuardConfig `mapstructure:"wireguard"`
|
||||
STUN STUNConfig `mapstructure:"stun"`
|
||||
TURN TURNConfig `mapstructure:"turn"`
|
||||
}
|
||||
|
||||
// AppConfig 应用配置
|
||||
type AppConfig struct {
|
||||
Version string `mapstructure:"version"` // 版本号
|
||||
BuildDate string `mapstructure:"build_date"` // 构建日期
|
||||
}
|
||||
|
||||
// ServerConfig 服务器配置
|
||||
type ServerConfig struct {
|
||||
Port int `mapstructure:"port"`
|
||||
Mode string `mapstructure:"mode"` // debug, release, test
|
||||
StaticPath string `mapstructure:"static_path"` // 前端静态文件目录
|
||||
}
|
||||
|
||||
// DatabaseConfig 数据库配置
|
||||
type DatabaseConfig struct {
|
||||
Type string `mapstructure:"type"`
|
||||
Path string `mapstructure:"path"`
|
||||
}
|
||||
|
||||
// JWTConfig JWT 配置
|
||||
type JWTConfig struct {
|
||||
Secret string `mapstructure:"secret"`
|
||||
AccessTokenDur string `mapstructure:"access_token_duration"`
|
||||
RefreshTokenDur string `mapstructure:"refresh_token_duration"`
|
||||
}
|
||||
|
||||
// LogConfig 日志配置
|
||||
type LogConfig struct {
|
||||
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"`
|
||||
}
|
||||
|
||||
// EncryptionConfig 加密配置
|
||||
type EncryptionConfig struct {
|
||||
NetworkSecretKey string `mapstructure:"network_secret_key"`
|
||||
}
|
||||
|
||||
// WireGuardConfig WireGuard 配置(固定使用用户态)
|
||||
type WireGuardConfig struct {
|
||||
// 已删除 PreferredMode 字段 - 统一使用 wireguard-go 用户态
|
||||
}
|
||||
|
||||
// STUNConfig STUN 配置
|
||||
type STUNConfig struct {
|
||||
DefaultServers []string `mapstructure:"default_servers"` // 默认 STUN 服务器列表
|
||||
SelectionStrategy string `mapstructure:"selection_strategy"` // 选择策略:auto, domestic, international, custom
|
||||
AutoTest bool `mapstructure:"auto_test"` // 是否启用自动测试
|
||||
TestInterval int `mapstructure:"test_interval"` // 测试间隔(秒)
|
||||
Timeout int `mapstructure:"timeout"` // 超时时间(秒)
|
||||
}
|
||||
|
||||
// TURNConfig TURN 配置
|
||||
type TURNConfig struct {
|
||||
DefaultServers []TURNServerConfig `mapstructure:"default_servers"` // 默认 TURN 服务器列表
|
||||
}
|
||||
|
||||
// TURNServerConfig TURN 服务器配置
|
||||
type TURNServerConfig struct {
|
||||
URL string `mapstructure:"url"` // TURN 服务器 URL
|
||||
Username string `mapstructure:"username"` // 用户名
|
||||
Credential string `mapstructure:"credential"` // 凭证
|
||||
AuthType string `mapstructure:"auth_type"` // 鉴权方式:credential, token, secret
|
||||
}
|
||||
|
||||
// Load 加载配置文件
|
||||
func Load(configPath string) (*Config, error) {
|
||||
// 如果未指定配置文件路径,使用默认路径
|
||||
if configPath == "" {
|
||||
configPath = "config.yaml"
|
||||
}
|
||||
|
||||
// 检查配置文件是否存在
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
// 尝试从示例文件复制
|
||||
examplePath := "configs/config.example.yaml"
|
||||
if _, err := os.Stat(examplePath); err == nil {
|
||||
// 创建目录
|
||||
dir := filepath.Dir(configPath)
|
||||
if dir != "." {
|
||||
os.MkdirAll(dir, 0755)
|
||||
}
|
||||
// 复制示例配置
|
||||
data, _ := os.ReadFile(examplePath)
|
||||
os.WriteFile(configPath, data, 0644)
|
||||
}
|
||||
}
|
||||
|
||||
// 读取配置文件
|
||||
viper.SetConfigFile(configPath)
|
||||
viper.AutomaticEnv()
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return nil, fmt.Errorf("读取配置文件失败:%w", err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := viper.Unmarshal(&config); err != nil {
|
||||
return nil, fmt.Errorf("解析配置文件失败:%w", err)
|
||||
}
|
||||
|
||||
// 自动填充默认值
|
||||
if config.Server.Port == 0 {
|
||||
config.Server.Port = 9531
|
||||
}
|
||||
if config.Server.Mode == "" {
|
||||
config.Server.Mode = "release"
|
||||
}
|
||||
|
||||
// 自动生成 JWT Secret
|
||||
if config.JWT.Secret == "" {
|
||||
config.JWT.Secret = generateJWTSecret()
|
||||
}
|
||||
|
||||
// 自动生成加密密钥
|
||||
if config.Encryption.NetworkSecretKey == "" {
|
||||
config.Encryption.NetworkSecretKey = generateEncryptionKey()
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// generateJWTSecret 使用 crypto/rand 生成随机 JWT Secret
|
||||
func generateJWTSecret() string {
|
||||
b := make([]byte, 32)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
// 极端情况回退(几乎不会发生)
|
||||
return uuid.New().String()
|
||||
}
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
// generateEncryptionKey 使用 crypto/rand 生成加密密钥
|
||||
func generateEncryptionKey() string {
|
||||
key := make([]byte, 32)
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
// 极端情况回退(几乎不会发生)
|
||||
return uuid.New().String() + uuid.New().String()
|
||||
}
|
||||
return hex.EncodeToString(key)
|
||||
}
|
||||
Reference in New Issue
Block a user