package config import ( "encoding/json" "errors" "os" "time" ) type Config struct { HTTP HTTPConfig `json:"http"` Redis RedisConfig `json:"redis"` Room RoomConfig `json:"room"` Proxy ProxyConfig `json:"proxy"` WebSocket WebSocketConfig `json:"websocket"` Source SourceConfig `json:"source"` } type HTTPConfig struct { Addr string `json:"addr"` AllowedOrigins []string `json:"allowedOrigins"` } type RedisConfig struct { Addr string `json:"addr"` Password string `json:"password"` DB int `json:"db"` } type RoomConfig struct { CodeLength int `json:"codeLength"` EmptyTTL Duration `json:"emptyTtl"` OwnerReconnectHold Duration `json:"ownerReconnectHold"` } type ProxyConfig struct { Enabled bool `json:"enabled"` RequestTimeout Duration `json:"requestTimeout"` MaxIdleConns int `json:"maxIdleConns"` ResponseHeaderBytes int64 `json:"responseHeaderBytes"` } type WebSocketConfig struct { PingInterval Duration `json:"pingInterval"` PongTimeout Duration `json:"pongTimeout"` WriteTimeout Duration `json:"writeTimeout"` } type SourceConfig struct { DefaultMode string `json:"defaultMode"` } func Load(path string) (Config, error) { if path == "" { path = os.Getenv("SYNCTV_CONFIG") } if path == "" { path = "config/config.json" } cfg := Default() b, err := os.ReadFile(path) if err != nil { return Config{}, err } if err := json.Unmarshal(b, &cfg); err != nil { return Config{}, err } if err := cfg.Validate(); err != nil { return Config{}, err } return cfg, nil } func Default() Config { return Config{ HTTP: HTTPConfig{ Addr: ":8080", AllowedOrigins: []string{"*"}, }, Redis: RedisConfig{ Addr: "localhost:6379", }, Room: RoomConfig{ CodeLength: 6, EmptyTTL: Duration(30 * time.Minute), OwnerReconnectHold: Duration(30 * time.Second), }, Proxy: ProxyConfig{ Enabled: true, RequestTimeout: 0, MaxIdleConns: 256, ResponseHeaderBytes: 1 << 20, }, WebSocket: WebSocketConfig{ PingInterval: Duration(25 * time.Second), PongTimeout: Duration(60 * time.Second), WriteTimeout: Duration(10 * time.Second), }, Source: SourceConfig{ DefaultMode: "direct", }, } } func (c Config) Validate() error { if c.HTTP.Addr == "" { return errors.New("http.addr is required") } if c.Redis.Addr == "" { return errors.New("redis.addr is required") } if c.Room.CodeLength < 4 { return errors.New("room.codeLength must be at least 4") } if c.Room.EmptyTTL <= 0 { return errors.New("room.emptyTtl must be positive") } if c.Source.DefaultMode != "direct" && c.Source.DefaultMode != "proxy" { return errors.New("source.defaultMode must be direct or proxy") } return nil }