diff --git a/src/interfaces/ReverseProxy.ts b/src/interfaces/ReverseProxy.ts index 50d9816c..50d79c93 100644 --- a/src/interfaces/ReverseProxy.ts +++ b/src/interfaces/ReverseProxy.ts @@ -86,6 +86,7 @@ export interface ReverseProxyDomain { type: ReverseProxyDomainType; target_cluster?: string; supports_custom_ports?: boolean; + require_subdomain?: boolean; } export enum ReverseProxyDomainType { diff --git a/src/modules/reverse-proxy/ReverseProxyModal.tsx b/src/modules/reverse-proxy/ReverseProxyModal.tsx index 3fd3c361..7af01a87 100644 --- a/src/modules/reverse-proxy/ReverseProxyModal.tsx +++ b/src/modules/reverse-proxy/ReverseProxyModal.tsx @@ -248,8 +248,12 @@ export default function ReverseProxyModal({ ); const canContinueToSettings = useMemo(() => { + const subdomainRequired = + selectedDomain?.require_subdomain === true; const isSubdomainValid = - subdomain.length > 0 && baseDomain.length > 0 && !domainAlreadyExists; + baseDomain.length > 0 && + !domainAlreadyExists && + (subdomain.length > 0 || !subdomainRequired); const isValidPort = (port: number) => port >= 1 && port <= 65535; const hasHttpEndpoint = !isL4Mode && targets.length > 0; const hasL4Endpoint = @@ -264,6 +268,7 @@ export default function ReverseProxyModal({ subdomain, baseDomain, domainAlreadyExists, + selectedDomain, serviceMode, targets.length, isL4Mode, @@ -444,6 +449,7 @@ export default function ReverseProxyModal({ baseDomain={baseDomain} onBaseDomainChange={setBaseDomain} domainAlreadyExists={domainAlreadyExists} + subdomainRequired={selectedDomain?.require_subdomain === true} clusterOffline={ reverseProxy?.proxy_cluster && !isClusterConnected ? { clusterName: reverseProxy.proxy_cluster } diff --git a/src/modules/reverse-proxy/domain/ReverseProxyDomainInput.tsx b/src/modules/reverse-proxy/domain/ReverseProxyDomainInput.tsx index 137dbbe2..982fbeec 100644 --- a/src/modules/reverse-proxy/domain/ReverseProxyDomainInput.tsx +++ b/src/modules/reverse-proxy/domain/ReverseProxyDomainInput.tsx @@ -13,6 +13,7 @@ type Props = { baseDomain: string; onBaseDomainChange: (value: string) => void; domainAlreadyExists: boolean; + subdomainRequired?: boolean; clusterOffline?: { clusterName: string; }; @@ -24,13 +25,16 @@ export default function ReverseProxyDomainInput({ baseDomain, onBaseDomainChange, domainAlreadyExists, + subdomainRequired = false, clusterOffline, }: Readonly) { return (
- Enter a subdomain and select a domain for your service. + {subdomainRequired + ? "Enter a subdomain and select a domain for your service." + : "Optionally enter a subdomain, or use the domain directly."}
@@ -47,7 +51,7 @@ export default function ReverseProxyDomainInput({ ? "This domain is already used by another service." : undefined } - placeholder={"myapp"} + placeholder={subdomainRequired ? "myapp" : "myapp (optional)"} className="!rounded-r-none !border-r-0" />
diff --git a/src/modules/reverse-proxy/domain/useReverseProxyDomain.ts b/src/modules/reverse-proxy/domain/useReverseProxyDomain.ts index 3e24825a..25eca5c5 100644 --- a/src/modules/reverse-proxy/domain/useReverseProxyDomain.ts +++ b/src/modules/reverse-proxy/domain/useReverseProxyDomain.ts @@ -23,6 +23,13 @@ function parseDomain( .filter((d) => d.domain) .sort((a, b) => b.domain.length - a.domain.length); for (const d of sorted) { + if (fullDomain === d.domain) { + return { + subdomain: "", + baseDomain: d.domain, + isCustom: d.type === ReverseProxyDomainType.CUSTOM, + }; + } if (fullDomain.endsWith(`.${d.domain}`)) { return { subdomain: fullDomain.slice(0, -(d.domain.length + 1)), @@ -103,7 +110,11 @@ export function useReverseProxyDomain({ return customDomain?.domain || freeDomain?.domain || ""; }); - const fullDomain = baseDomain ? `${subdomain}.${baseDomain}` : subdomain; + const fullDomain = baseDomain + ? subdomain + ? `${subdomain}.${baseDomain}` + : baseDomain + : subdomain; const domainAlreadyExists = useMemo(() => { if (!reverseProxies || !fullDomain) return false;