From 3d1816a640c67f451ae9f2b6432fd3fc98ff726a Mon Sep 17 00:00:00 2001 From: grendervill Date: Sat, 19 Sep 2026 19:58:32 +0300 Subject: [PATCH] =?UTF-8?q?feat(config):=20=D1=81=D1=85=D0=B5=D0=BC=D0=B0?= =?UTF-8?q?=20URL=20=D0=B2=20meta=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8?= =?UTF-8?q?=D1=82=20=D0=BE=D1=82=20TLS=5FENABLED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - при установке без TLS (--skip-tls, стенд без домена) клиент получает http:// и ws:// вместо неработающих https:// и wss:// - установщик пишет TLS_ENABLED в .env; тесты фиксируют обе схемы --- deploy/install.sh | 3 +++ internal/config/config.go | 35 ++++++++++++++++++++++++++++++++-- internal/config/config_test.go | 15 +++++++++++++-- internal/meta/meta.go | 2 +- internal/meta/meta_test.go | 1 + internal/server/server_test.go | 1 + 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/deploy/install.sh b/deploy/install.sh index 77e58d2..dd4451b 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -496,6 +496,9 @@ APP_IMAGE=${APP_IMAGE} CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG} LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG} +# --- TLS --- +TLS_ENABLED=$([ "$SKIP_TLS" = "1" ] && echo false || echo true) + # --- интерполяция compose (пути и профиль) --- GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR} GLCHAT_CADDY_PROFILE=${CADDY_PROFILE} diff --git a/internal/config/config.go b/internal/config/config.go index ff95748..7a90f9c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -28,6 +28,7 @@ type Config struct { LogFormat string ReadPoolSize int MaxUploadSize int64 + TLSEnabled bool Version string Commit string BuildDate string @@ -50,6 +51,7 @@ func Load() (Config, error) { LogFormat: strings.ToLower(env("LOG_FORMAT", "json")), ReadPoolSize: envInt("SQLITE_READ_POOL", 4), MaxUploadSize: envInt64("MAX_UPLOAD_SIZE", 26214400), + TLSEnabled: envBool("TLS_ENABLED", true), Version: env("APP_VERSION", "dev"), Commit: env("APP_COMMIT", "none"), BuildDate: env("APP_BUILD_DATE", "unknown"), @@ -74,8 +76,25 @@ func Load() (Config, error) { return cfg, nil } -func (c Config) BaseURL() string { return "https://" + c.Domain } -func (c Config) FilesURL() string { return "https://" + c.FilesDomain } +// Scheme выбирается установщиком: при установке без TLS (--skip-tls, +// например стенд без домена) клиент должен получать 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 { level, err := parseLogLevel(c.LogLevel) @@ -119,6 +138,18 @@ func envInt(key string, fallback int) int { 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 { v, ok := os.LookupEnv(key) if !ok || v == "" { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 58bf2af..da69603 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -18,6 +18,7 @@ func TestLoadDefaults(t *testing.T) { t.Setenv("APP_VERSION", "") t.Setenv("APP_COMMIT", "") t.Setenv("APP_BUILD_DATE", "") + t.Setenv("TLS_ENABLED", "") cfg, err := Load() if err != nil { @@ -44,6 +45,12 @@ func TestLoadDefaults(t *testing.T) { if cfg.Version != "dev" { 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 { 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_COMMIT", "abc1234") t.Setenv("SHUTDOWN_TIMEOUT_SECONDS", "5") + t.Setenv("TLS_ENABLED", "false") cfg, err := Load() if err != nil { @@ -88,12 +96,15 @@ func TestLoadEnvOverrides(t *testing.T) { if cfg.LogFormat != "text" { 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()) } - if cfg.FilesURL() != "https://files.gl.mhspx.su" { + if cfg.FilesURL() != "http://files.gl.mhspx.su" { 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) { diff --git a/internal/meta/meta.go b/internal/meta/meta.go index 2a380a0..b3132a0 100644 --- a/internal/meta/meta.go +++ b/internal/meta/meta.go @@ -36,7 +36,7 @@ func New(cfg config.Config) Response { APIVersion: APIVersion, BaseURL: cfg.BaseURL(), FilesURL: cfg.FilesURL(), - GatewayURL: "wss://" + cfg.Domain + "/gateway", + GatewayURL: cfg.GatewayURL(), RTCPath: "/rtc", MaxUploadSize: cfg.MaxUploadSize, Features: Features{ diff --git a/internal/meta/meta_test.go b/internal/meta/meta_test.go index bb3a27f..c480f1c 100644 --- a/internal/meta/meta_test.go +++ b/internal/meta/meta_test.go @@ -16,6 +16,7 @@ func TestNewBuildsMetaPayload(t *testing.T) { Commit: "abc1234", BuildDate: "2026-09-19T00:00:00Z", MaxUploadSize: 26214400, + TLSEnabled: true, } resp := New(cfg) diff --git a/internal/server/server_test.go b/internal/server/server_test.go index ae4dd84..fdf1060 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -41,6 +41,7 @@ func newTestServer(t *testing.T) (*Server, *database.DB) { Commit: "deadbee", BuildDate: "2026-09-19T00:00:00Z", MaxUploadSize: 26214400, + TLSEnabled: true, LogLevel: "error", LogFormat: "json", }