feat(config): схема URL в meta зависит от TLS_ENABLED

- при установке без TLS (--skip-tls, стенд без домена) клиент получает
  http:// и ws:// вместо неработающих https:// и wss://
- установщик пишет TLS_ENABLED в .env; тесты фиксируют обе схемы
This commit is contained in:
2026-09-19 19:58:32 +03:00
parent 6804a316cf
commit 3d1816a640
6 changed files with 52 additions and 5 deletions
+3
View File
@@ -496,6 +496,9 @@ APP_IMAGE=${APP_IMAGE}
CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG} CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG}
LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG} LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG}
# --- TLS ---
TLS_ENABLED=$([ "$SKIP_TLS" = "1" ] && echo false || echo true)
# --- интерполяция compose (пути и профиль) --- # --- интерполяция compose (пути и профиль) ---
GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR} GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR}
GLCHAT_CADDY_PROFILE=${CADDY_PROFILE} GLCHAT_CADDY_PROFILE=${CADDY_PROFILE}
+33 -2
View File
@@ -28,6 +28,7 @@ type Config struct {
LogFormat string LogFormat string
ReadPoolSize int ReadPoolSize int
MaxUploadSize int64 MaxUploadSize int64
TLSEnabled bool
Version string Version string
Commit string Commit string
BuildDate string BuildDate string
@@ -50,6 +51,7 @@ func Load() (Config, error) {
LogFormat: strings.ToLower(env("LOG_FORMAT", "json")), LogFormat: strings.ToLower(env("LOG_FORMAT", "json")),
ReadPoolSize: envInt("SQLITE_READ_POOL", 4), ReadPoolSize: envInt("SQLITE_READ_POOL", 4),
MaxUploadSize: envInt64("MAX_UPLOAD_SIZE", 26214400), MaxUploadSize: envInt64("MAX_UPLOAD_SIZE", 26214400),
TLSEnabled: envBool("TLS_ENABLED", true),
Version: env("APP_VERSION", "dev"), Version: env("APP_VERSION", "dev"),
Commit: env("APP_COMMIT", "none"), Commit: env("APP_COMMIT", "none"),
BuildDate: env("APP_BUILD_DATE", "unknown"), BuildDate: env("APP_BUILD_DATE", "unknown"),
@@ -74,8 +76,25 @@ func Load() (Config, error) {
return cfg, nil return cfg, nil
} }
func (c Config) BaseURL() string { return "https://" + c.Domain } // Scheme выбирается установщиком: при установке без TLS (--skip-tls,
func (c Config) FilesURL() string { return "https://" + c.FilesDomain } // например стенд без домена) клиент должен получать http/ws, а не https/wss.
func (c Config) Scheme() string {
if c.TLSEnabled {
return "https"
}
return "http"
}
func (c Config) BaseURL() string { return c.Scheme() + "://" + c.Domain }
func (c Config) FilesURL() string { return c.Scheme() + "://" + c.FilesDomain }
func (c Config) GatewayURL() string {
scheme := "ws"
if c.TLSEnabled {
scheme = "wss"
}
return scheme + "://" + c.Domain + "/gateway"
}
func (c Config) LogLevelNumeric() int { func (c Config) LogLevelNumeric() int {
level, err := parseLogLevel(c.LogLevel) level, err := parseLogLevel(c.LogLevel)
@@ -119,6 +138,18 @@ func envInt(key string, fallback int) int {
return n return n
} }
func envBool(key string, fallback bool) bool {
v, ok := os.LookupEnv(key)
if !ok || v == "" {
return fallback
}
parsed, err := strconv.ParseBool(v)
if err != nil {
return fallback
}
return parsed
}
func envInt64(key string, fallback int64) int64 { func envInt64(key string, fallback int64) int64 {
v, ok := os.LookupEnv(key) v, ok := os.LookupEnv(key)
if !ok || v == "" { if !ok || v == "" {
+13 -2
View File
@@ -18,6 +18,7 @@ func TestLoadDefaults(t *testing.T) {
t.Setenv("APP_VERSION", "") t.Setenv("APP_VERSION", "")
t.Setenv("APP_COMMIT", "") t.Setenv("APP_COMMIT", "")
t.Setenv("APP_BUILD_DATE", "") t.Setenv("APP_BUILD_DATE", "")
t.Setenv("TLS_ENABLED", "")
cfg, err := Load() cfg, err := Load()
if err != nil { if err != nil {
@@ -44,6 +45,12 @@ func TestLoadDefaults(t *testing.T) {
if cfg.Version != "dev" { if cfg.Version != "dev" {
t.Errorf("Version = %q, want dev", cfg.Version) t.Errorf("Version = %q, want dev", cfg.Version)
} }
if !cfg.TLSEnabled {
t.Error("TLSEnabled = false, want true by default")
}
if cfg.BaseURL() != "https://localhost" {
t.Errorf("BaseURL() = %q", cfg.BaseURL())
}
if cfg.LogLevelNumeric() != 0 { if cfg.LogLevelNumeric() != 0 {
t.Errorf("LogLevelNumeric() = %d, want 0 for info", cfg.LogLevelNumeric()) t.Errorf("LogLevelNumeric() = %d, want 0 for info", cfg.LogLevelNumeric())
} }
@@ -62,6 +69,7 @@ func TestLoadEnvOverrides(t *testing.T) {
t.Setenv("APP_VERSION", "v0.1.0") t.Setenv("APP_VERSION", "v0.1.0")
t.Setenv("APP_COMMIT", "abc1234") t.Setenv("APP_COMMIT", "abc1234")
t.Setenv("SHUTDOWN_TIMEOUT_SECONDS", "5") t.Setenv("SHUTDOWN_TIMEOUT_SECONDS", "5")
t.Setenv("TLS_ENABLED", "false")
cfg, err := Load() cfg, err := Load()
if err != nil { if err != nil {
@@ -88,12 +96,15 @@ func TestLoadEnvOverrides(t *testing.T) {
if cfg.LogFormat != "text" { if cfg.LogFormat != "text" {
t.Errorf("LogFormat = %q", cfg.LogFormat) t.Errorf("LogFormat = %q", cfg.LogFormat)
} }
if cfg.BaseURL() != "https://gl.mhspx.su" { if cfg.BaseURL() != "http://gl.mhspx.su" {
t.Errorf("BaseURL() = %q", cfg.BaseURL()) t.Errorf("BaseURL() = %q", cfg.BaseURL())
} }
if cfg.FilesURL() != "https://files.gl.mhspx.su" { if cfg.FilesURL() != "http://files.gl.mhspx.su" {
t.Errorf("FilesURL() = %q", cfg.FilesURL()) t.Errorf("FilesURL() = %q", cfg.FilesURL())
} }
if cfg.GatewayURL() != "ws://gl.mhspx.su/gateway" {
t.Errorf("GatewayURL() = %q", cfg.GatewayURL())
}
} }
func TestLoadRejectsInvalidValues(t *testing.T) { func TestLoadRejectsInvalidValues(t *testing.T) {
+1 -1
View File
@@ -36,7 +36,7 @@ func New(cfg config.Config) Response {
APIVersion: APIVersion, APIVersion: APIVersion,
BaseURL: cfg.BaseURL(), BaseURL: cfg.BaseURL(),
FilesURL: cfg.FilesURL(), FilesURL: cfg.FilesURL(),
GatewayURL: "wss://" + cfg.Domain + "/gateway", GatewayURL: cfg.GatewayURL(),
RTCPath: "/rtc", RTCPath: "/rtc",
MaxUploadSize: cfg.MaxUploadSize, MaxUploadSize: cfg.MaxUploadSize,
Features: Features{ Features: Features{
+1
View File
@@ -16,6 +16,7 @@ func TestNewBuildsMetaPayload(t *testing.T) {
Commit: "abc1234", Commit: "abc1234",
BuildDate: "2026-09-19T00:00:00Z", BuildDate: "2026-09-19T00:00:00Z",
MaxUploadSize: 26214400, MaxUploadSize: 26214400,
TLSEnabled: true,
} }
resp := New(cfg) resp := New(cfg)
+1
View File
@@ -41,6 +41,7 @@ func newTestServer(t *testing.T) (*Server, *database.DB) {
Commit: "deadbee", Commit: "deadbee",
BuildDate: "2026-09-19T00:00:00Z", BuildDate: "2026-09-19T00:00:00Z",
MaxUploadSize: 26214400, MaxUploadSize: 26214400,
TLSEnabled: true,
LogLevel: "error", LogLevel: "error",
LogFormat: "json", LogFormat: "json",
} }