This commit is contained in:
2025-11-14 12:11:44 +08:00
commit 39ebf61572
88 changed files with 9999 additions and 0 deletions

105
internal/config/types.go Normal file
View File

@@ -0,0 +1,105 @@
package config
import (
"fmt"
"strconv"
"strings"
"time"
)
// Duration 提供更灵活的反序列化能力,同时兼容纯秒整数与 Go Duration 字符串。
type Duration time.Duration
// UnmarshalText 使 Viper 可以识别诸如 "30s"、"5m" 或纯数字秒值等配置写法。
func (d *Duration) UnmarshalText(text []byte) error {
raw := strings.TrimSpace(string(text))
if raw == "" {
*d = Duration(0)
return nil
}
if seconds, err := time.ParseDuration(raw); err == nil {
*d = Duration(seconds)
return nil
}
if intVal, err := parseInt(raw); err == nil {
*d = Duration(time.Duration(intVal) * time.Second)
return nil
}
return fmt.Errorf("invalid duration value: %s", raw)
}
// DurationValue 返回真实的 time.Duration便于调用方计算。
func (d Duration) DurationValue() time.Duration {
return time.Duration(d)
}
// parseInt 支持十进制或 0x 前缀的十六进制字符串解析。
func parseInt(value string) (int64, error) {
if strings.HasPrefix(value, "0x") || strings.HasPrefix(value, "0X") {
return strconv.ParseInt(value, 0, 64)
}
return strconv.ParseInt(value, 10, 64)
}
// GlobalConfig 描述全局运行时行为,所有 Hub 共享同一份参数。
type GlobalConfig struct {
ListenPort int `mapstructure:"ListenPort"`
LogLevel string `mapstructure:"LogLevel"`
LogFilePath string `mapstructure:"LogFilePath"`
LogMaxSize int `mapstructure:"LogMaxSize"`
LogMaxBackups int `mapstructure:"LogMaxBackups"`
LogCompress bool `mapstructure:"LogCompress"`
StoragePath string `mapstructure:"StoragePath"`
CacheTTL Duration `mapstructure:"CacheTTL"`
MaxMemoryCache int64 `mapstructure:"MaxMemoryCacheSize"`
MaxRetries int `mapstructure:"MaxRetries"`
InitialBackoff Duration `mapstructure:"InitialBackoff"`
UpstreamTimeout Duration `mapstructure:"UpstreamTimeout"`
}
// HubConfig 决定单个代理实例如何与下游/上游交互。
type HubConfig struct {
Name string `mapstructure:"Name"`
Domain string `mapstructure:"Domain"`
Upstream string `mapstructure:"Upstream"`
Proxy string `mapstructure:"Proxy"`
Type string `mapstructure:"Type"`
Username string `mapstructure:"Username"`
Password string `mapstructure:"Password"`
CacheTTL Duration `mapstructure:"CacheTTL"`
EnableHeadCheck bool `mapstructure:"EnableHeadCheck"`
}
// Config 是 TOML 文件映射的整体结构。
type Config struct {
Global GlobalConfig `mapstructure:",squash"`
Hubs []HubConfig `mapstructure:"Hub"`
}
// HasCredentials 表示当前 Hub 是否配置了完整的上游凭证。
func (h HubConfig) HasCredentials() bool {
return h.Username != "" && h.Password != ""
}
// AuthMode 输出 `credentialed` 或 `anonymous`,供日志字段使用。
func (h HubConfig) AuthMode() string {
if h.HasCredentials() {
return "credentialed"
}
return "anonymous"
}
// CredentialModes 返回所有 Hub 的鉴权模式摘要,例如 secure:credentialed。
func CredentialModes(hubs []HubConfig) []string {
if len(hubs) == 0 {
return nil
}
result := make([]string, len(hubs))
for i, hub := range hubs {
result[i] = fmt.Sprintf("%s:%s", hub.Name, hub.AuthMode())
}
return result
}