namespace DorkNet.Server.Services; /// Single source of truth for the deployment apex domain. /// Read from DORKNET_DOMAIN env var (or config key /// Domain:Apex) at startup. Defaults to localhost. Replaces /// per-controller [Host("api.rec.net","api.localhost")] filters — /// allowed hosts are derived as {apex} + *.{apex}, fed /// into HostFilteringMiddleware. Subdomain-discriminating handlers /// (Cdn vs Img on path "/{*path}") branch on /// Request.Host.Host.Split('.')[0]. public sealed class DomainConfig { public string Apex { get; } public string Scheme { get; } public DomainConfig(string apex, string scheme = "https") { Apex = apex; Scheme = NormalizeScheme(scheme); } public string Sub(string prefix) => $"{prefix}.{Apex}"; public string Url(string prefix, string path = "") { var host = string.IsNullOrEmpty(prefix) ? Apex : Sub(prefix); if (string.IsNullOrEmpty(path)) return $"{Scheme}://{host}"; return $"{Scheme}://{host}{(path.StartsWith('/') ? path : "/" + path)}"; } public static bool MatchesSubdomain(string host, string prefix) => host.StartsWith(prefix + ".", StringComparison.OrdinalIgnoreCase); private static string NormalizeScheme(string? value) { var scheme = string.IsNullOrWhiteSpace(value) ? "https" : value.Trim().TrimEnd(':', '/', '\\').ToLowerInvariant(); return scheme is "http" or "https" ? scheme : "https"; } }