2026-04-29 12:43:05 +08:00

155 lines
5.6 KiB
Go
Raw 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 (
"fmt"
"strings"
"time"
"hyapp/pkg/configx"
"hyapp/pkg/tencentrtc"
)
// Config 描述 gateway-service 启动所需的最小配置。
type Config struct {
HTTPAddr string `yaml:"http_addr"`
JWTSecret string `yaml:"jwt_secret"`
RoomServiceAddr string `yaml:"room_service_addr"`
UserServiceAddr string `yaml:"user_service_addr"`
AuthRateLimit AuthRateLimitConfig `yaml:"auth_rate_limit"`
TencentIM TencentIMConfig `yaml:"tencent_im"`
TencentRTC TencentRTCConfig `yaml:"tencent_rtc"`
}
// AuthRateLimitConfig 控制 gateway public auth 入口的 Redis 频控。
type AuthRateLimitConfig struct {
// Enabled 为 false 时关闭 gateway auth 入口频控。
Enabled bool `yaml:"enabled"`
// RedisAddr 是 public auth 频控 Redis 地址。
RedisAddr string `yaml:"redis_addr"`
// RedisPassword 是 Redis 鉴权密码,本地默认留空。
RedisPassword string `yaml:"redis_password"`
// RedisDB 是 Redis logical DB。
RedisDB int `yaml:"redis_db"`
// KeyPrefix 是频控 key 前缀,用于区分环境和服务。
KeyPrefix string `yaml:"key_prefix"`
// WindowSec 是固定窗口秒数。
WindowSec int64 `yaml:"window_sec"`
// IPLimit 限制同一入口 IP 对所有 public auth API 的请求数。
IPLimit int `yaml:"ip_limit"`
// DeviceIDLimit 限制同一 device_id 对登录、注册和 refresh 的请求数。
DeviceIDLimit int `yaml:"device_id_limit"`
// ProviderIPLimit 限制同一 IP 对同一三方 provider 的注册/登录请求数。
ProviderIPLimit int `yaml:"provider_ip_limit"`
// DisplayUserIDIPLimit 限制同一 IP 对同一 display_user_id 的密码尝试。
DisplayUserIDIPLimit int `yaml:"display_user_id_ip_limit"`
// DisplayUserIDLimit 限制同一 display_user_id 被跨 IP 喷射尝试。
DisplayUserIDLimit int `yaml:"display_user_id_limit"`
// SessionIDIPLimit 限制同一 IP 对同一 session_id 的 logout 请求数。
SessionIDIPLimit int `yaml:"session_id_ip_limit"`
}
// TencentIMConfig 描述 gateway 给客户端签发腾讯云 IM UserSig 的配置。
type TencentIMConfig struct {
// SDKAppID 是腾讯云 IM 控制台分配的应用 ID。
SDKAppID int64 `yaml:"sdk_app_id"`
// SecretKey 只允许出现在服务端配置中,不能下发给客户端。
SecretKey string `yaml:"secret_key"`
// UserSigTTL 是客户端 IM 登录票据有效期。
UserSigTTL time.Duration `yaml:"user_sig_ttl"`
// CallbackURL 是在腾讯云 IM 控制台配置的服务端回调地址。
CallbackURL string `yaml:"callback_url"`
// CallbackAuthToken 是腾讯云 IM 回调鉴权 token只用于校验回调来源。
CallbackAuthToken string `yaml:"callback_auth_token"`
}
// TencentRTCConfig 描述 gateway 给客户端签发腾讯 RTC 进房 UserSig 的配置。
type TencentRTCConfig struct {
// Enabled 控制 RTC token endpoint 是否可以对外签发,配置缺失时必须 fail-closed。
Enabled bool `yaml:"enabled"`
// SDKAppID 是腾讯 RTC 控制台分配的应用 ID。
SDKAppID int64 `yaml:"sdk_app_id"`
// SecretKey 只允许出现在服务端配置中,不能下发给客户端。
SecretKey string `yaml:"secret_key"`
// UserSigTTL 是客户端 RTC 进房票据有效期。
UserSigTTL time.Duration `yaml:"user_sig_ttl"`
// RoomIDType 首版固定 string确保客户端只使用 TRTC strRoomId。
RoomIDType string `yaml:"room_id_type"`
// AppScene 首版固定 voice_chat_room所有端必须一致。
AppScene string `yaml:"app_scene"`
}
// Default 返回本地开发默认配置。
func Default() Config {
return Config{
HTTPAddr: ":13000",
JWTSecret: "gateway-dev-secret",
RoomServiceAddr: "127.0.0.1:13001",
UserServiceAddr: "127.0.0.1:13005",
AuthRateLimit: AuthRateLimitConfig{
Enabled: true,
RedisAddr: "127.0.0.1:13379",
KeyPrefix: "gateway:auth:rate:",
WindowSec: 60,
IPLimit: 120,
DeviceIDLimit: 30,
ProviderIPLimit: 20,
DisplayUserIDIPLimit: 10,
DisplayUserIDLimit: 50,
SessionIDIPLimit: 30,
},
TencentIM: TencentIMConfig{
UserSigTTL: 24 * time.Hour,
},
TencentRTC: TencentRTCConfig{
UserSigTTL: 2 * time.Hour,
RoomIDType: "string",
AppScene: "voice_chat_room",
},
}
}
// Load 从独立 config.yaml 读取 gateway-service 配置。
func Load(path string) (Config, error) {
cfg := Default()
if path == "" {
if err := cfg.Normalize(); err != nil {
return Config{}, err
}
return cfg, nil
}
if err := configx.LoadYAML(path, &cfg); err != nil {
return Config{}, err
}
if err := cfg.Normalize(); err != nil {
return Config{}, err
}
return cfg, nil
}
// Normalize fills policy defaults and rejects unsupported RTC room/app modes at startup.
func (cfg *Config) Normalize() error {
cfg.TencentRTC.RoomIDType = strings.TrimSpace(cfg.TencentRTC.RoomIDType)
if cfg.TencentRTC.RoomIDType == "" {
cfg.TencentRTC.RoomIDType = tencentrtc.RoomIDTypeString
}
if cfg.TencentRTC.RoomIDType != tencentrtc.RoomIDTypeString {
// Numeric TRTC roomId would fork users into a different room than internal string room_id.
return fmt.Errorf("tencent_rtc.room_id_type must be %q", tencentrtc.RoomIDTypeString)
}
cfg.TencentRTC.AppScene = strings.TrimSpace(cfg.TencentRTC.AppScene)
if cfg.TencentRTC.AppScene == "" {
cfg.TencentRTC.AppScene = tencentrtc.AppSceneVoiceChatRoom
}
if cfg.TencentRTC.AppScene != tencentrtc.AppSceneVoiceChatRoom {
// v1 has no gateway policy surface for multiple RTC scenes, so reject drift early.
return fmt.Errorf("tencent_rtc.app_scene must be %q", tencentrtc.AppSceneVoiceChatRoom)
}
return nil
}