mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-29 06:10:47 +00:00
Fix api call
This commit is contained in:
@@ -321,130 +321,49 @@ export async function getTraefikConfig(
|
||||
config_output.http.services = {};
|
||||
}
|
||||
|
||||
const availableServers = (targets as TargetWithSite[]).filter(
|
||||
(target: TargetWithSite) => {
|
||||
if (!target.enabled) return false;
|
||||
const additionalMiddlewares =
|
||||
config.getRawConfig().traefik.additional_middlewares || [];
|
||||
|
||||
const anySitesOnline = (targets as TargetWithSite[]).some(
|
||||
(t: TargetWithSite) => t.site.online
|
||||
);
|
||||
if (anySitesOnline && !target.site.online) return false;
|
||||
const routerMiddlewares = [
|
||||
badgerMiddlewareName,
|
||||
...additionalMiddlewares
|
||||
];
|
||||
|
||||
if (target.site.type === "local" || target.site.type === "wireguard") {
|
||||
return target.ip && target.port && target.method;
|
||||
} else if (target.site.type === "newt") {
|
||||
return target.internalPort && target.method && target.site.subnet;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
let rule = `Host(\`${fullDomain}\`)`;
|
||||
|
||||
const hasHealthyServers = availableServers.length > 0;
|
||||
|
||||
let showMaintenancePage = false;
|
||||
if (resource.maintenanceModeEnabled) {
|
||||
if (resource.maintenanceModeType === "forced") {
|
||||
showMaintenancePage = true;
|
||||
logger.debug(
|
||||
`Resource ${resource.name} (${fullDomain}) is in FORCED maintenance mode`
|
||||
);
|
||||
} else if (resource.maintenanceModeType === "automatic") {
|
||||
showMaintenancePage = !hasHealthyServers;
|
||||
if (showMaintenancePage) {
|
||||
logger.warn(
|
||||
`Resource ${resource.name} (${fullDomain}) has no healthy servers - showing maintenance page (AUTOMATIC mode)`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showMaintenancePage) {
|
||||
const maintenanceServiceName = `${key}-maintenance-service`;
|
||||
const maintenanceRouterName = `${key}-maintenance-router`;
|
||||
const rewriteMiddlewareName = `${key}-maintenance-rewrite`;
|
||||
|
||||
const entrypointHttp = config.getRawConfig().traefik.http_entrypoint;
|
||||
const entrypointHttps = config.getRawConfig().traefik.https_entrypoint;
|
||||
|
||||
const fullDomain = resource.fullDomain;
|
||||
const domainParts = fullDomain.split(".");
|
||||
const wildCard = resource.subdomain
|
||||
? `*.${domainParts.slice(1).join(".")}`
|
||||
: fullDomain;
|
||||
|
||||
const tls = {
|
||||
certResolver: resource.domainCertResolver?.trim() ||
|
||||
config.getRawConfig().traefik.cert_resolver,
|
||||
...(config.getRawConfig().traefik.prefer_wildcard_cert
|
||||
? { domains: [{ main: wildCard }] }
|
||||
: {})
|
||||
};
|
||||
|
||||
const maintenancePort = config.getRawConfig().server.next_port;
|
||||
const maintenanceHost = config.getRawConfig().server.internal_hostname;
|
||||
|
||||
config_output.http.services[maintenanceServiceName] = {
|
||||
loadBalancer: {
|
||||
servers: [{ url: `http://${maintenanceHost}:${maintenancePort}` }],
|
||||
passHostHeader: true
|
||||
}
|
||||
};
|
||||
|
||||
// middleware to rewrite path to /maintenance-screen
|
||||
if (!config_output.http.middlewares) {
|
||||
config_output.http.middlewares = {};
|
||||
}
|
||||
|
||||
config_output.http.middlewares[rewriteMiddlewareName] = {
|
||||
replacePathRegex: {
|
||||
regex: "^/(.*)",
|
||||
replacement: "/maintenance-screen"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const rule = `Host(\`${fullDomain}\`)`;
|
||||
|
||||
console.log('DEBUG: Generated rule:', rule); // Should show: Host(`pangolin.pallavi.fosrl.io`)
|
||||
|
||||
config_output.http.routers[maintenanceRouterName] = {
|
||||
entryPoints: [resource.ssl ? entrypointHttps : entrypointHttp],
|
||||
service: maintenanceServiceName,
|
||||
middlewares: [rewriteMiddlewareName],
|
||||
rule: rule,
|
||||
priority: 2000,
|
||||
...(resource.ssl ? { tls } : {})
|
||||
};
|
||||
|
||||
if (resource.ssl) {
|
||||
config_output.http.routers[`${maintenanceRouterName}-redirect`] = {
|
||||
entryPoints: [entrypointHttp],
|
||||
middlewares: [redirectHttpsMiddlewareName, rewriteMiddlewareName],
|
||||
service: maintenanceServiceName,
|
||||
rule: rule,
|
||||
priority: 2000
|
||||
};
|
||||
}
|
||||
|
||||
logger.info(`Maintenance mode active for ${fullDomain}`);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const domainParts = fullDomain.split(".");
|
||||
let wildCard;
|
||||
if (domainParts.length <= 2) {
|
||||
wildCard = `*.${domainParts.join(".")}`;
|
||||
// priority logic
|
||||
let priority: number;
|
||||
if (resource.priority && resource.priority != 100) {
|
||||
priority = resource.priority;
|
||||
} else {
|
||||
wildCard = `*.${domainParts.slice(1).join(".")}`;
|
||||
priority = 100;
|
||||
if (resource.path && resource.pathMatchType) {
|
||||
priority += 10;
|
||||
if (resource.pathMatchType === "exact") {
|
||||
priority += 5;
|
||||
} else if (resource.pathMatchType === "prefix") {
|
||||
priority += 3;
|
||||
} else if (resource.pathMatchType === "regex") {
|
||||
priority += 2;
|
||||
}
|
||||
if (resource.path === "/") {
|
||||
priority = 1; // lowest for catch-all
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!resource.subdomain) {
|
||||
wildCard = resource.fullDomain;
|
||||
if (resource.ssl) {
|
||||
config_output.http.routers![routerName + "-redirect"] = {
|
||||
entryPoints: [
|
||||
config.getRawConfig().traefik.http_entrypoint
|
||||
],
|
||||
middlewares: [redirectHttpsMiddlewareName],
|
||||
service: serviceName,
|
||||
rule: rule,
|
||||
priority: priority
|
||||
};
|
||||
}
|
||||
|
||||
const configDomain = config.getDomain(resource.domainId);
|
||||
|
||||
let tls = {};
|
||||
if (!privateConfig.getRawPrivateConfig().flags.use_pangolin_dns) {
|
||||
const domainParts = fullDomain.split(".");
|
||||
@@ -510,13 +429,101 @@ export async function getTraefikConfig(
|
||||
}
|
||||
}
|
||||
|
||||
const additionalMiddlewares =
|
||||
config.getRawConfig().traefik.additional_middlewares || [];
|
||||
const availableServers = (targets as TargetWithSite[]).filter(
|
||||
(target: TargetWithSite) => {
|
||||
if (!target.enabled) return false;
|
||||
|
||||
const routerMiddlewares = [
|
||||
badgerMiddlewareName,
|
||||
...additionalMiddlewares
|
||||
];
|
||||
const anySitesOnline = (targets as TargetWithSite[]).some(
|
||||
(t: TargetWithSite) => t.site.online
|
||||
);
|
||||
if (anySitesOnline && !target.site.online) return false;
|
||||
|
||||
if (target.site.type === "local" || target.site.type === "wireguard") {
|
||||
return target.ip && target.port && target.method;
|
||||
} else if (target.site.type === "newt") {
|
||||
return target.internalPort && target.method && target.site.subnet;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
const hasHealthyServers = availableServers.length > 0;
|
||||
|
||||
let showMaintenancePage = false;
|
||||
if (resource.maintenanceModeEnabled) {
|
||||
if (resource.maintenanceModeType === "forced") {
|
||||
showMaintenancePage = true;
|
||||
// logger.debug(
|
||||
// `Resource ${resource.name} (${fullDomain}) is in FORCED maintenance mode`
|
||||
// );
|
||||
} else if (resource.maintenanceModeType === "automatic") {
|
||||
showMaintenancePage = !hasHealthyServers;
|
||||
if (showMaintenancePage) {
|
||||
logger.warn(
|
||||
`Resource ${resource.name} (${fullDomain}) has no healthy servers - showing maintenance page (AUTOMATIC mode)`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showMaintenancePage) {
|
||||
const maintenanceServiceName = `${key}-maintenance-service`;
|
||||
const maintenanceRouterName = `${key}-maintenance-router`;
|
||||
const rewriteMiddlewareName = `${key}-maintenance-rewrite`;
|
||||
|
||||
const entrypointHttp = config.getRawConfig().traefik.http_entrypoint;
|
||||
const entrypointHttps = config.getRawConfig().traefik.https_entrypoint;
|
||||
|
||||
const fullDomain = resource.fullDomain;
|
||||
const domainParts = fullDomain.split(".");
|
||||
const wildCard = resource.subdomain
|
||||
? `*.${domainParts.slice(1).join(".")}`
|
||||
: fullDomain;
|
||||
|
||||
const maintenancePort = config.getRawConfig().server.next_port;
|
||||
const maintenanceHost = config.getRawConfig().server.internal_hostname;
|
||||
|
||||
config_output.http.services[maintenanceServiceName] = {
|
||||
loadBalancer: {
|
||||
servers: [{ url: `http://${maintenanceHost}:${maintenancePort}` }],
|
||||
passHostHeader: true
|
||||
}
|
||||
};
|
||||
|
||||
// middleware to rewrite path to /maintenance-screen
|
||||
if (!config_output.http.middlewares) {
|
||||
config_output.http.middlewares = {};
|
||||
}
|
||||
|
||||
config_output.http.middlewares[rewriteMiddlewareName] = {
|
||||
replacePathRegex: {
|
||||
regex: "^/(.*)",
|
||||
replacement: "/maintenance-screen"
|
||||
}
|
||||
};
|
||||
|
||||
config_output.http.routers[maintenanceRouterName] = {
|
||||
entryPoints: [resource.ssl ? entrypointHttps : entrypointHttp],
|
||||
service: maintenanceServiceName,
|
||||
middlewares: [rewriteMiddlewareName],
|
||||
rule: rule,
|
||||
priority: 2000,
|
||||
...(resource.ssl ? { tls } : {})
|
||||
};
|
||||
|
||||
// Router to allow Next.js assets to load without rewrite
|
||||
config_output.http.routers[`${maintenanceRouterName}-assets`] = {
|
||||
entryPoints: [resource.ssl ? entrypointHttps : entrypointHttp],
|
||||
service: maintenanceServiceName,
|
||||
rule: `Host(\`${fullDomain}\`) && (PathPrefix(\`/_next\`) || PathRegexp(\`^/__nextjs*\`))`,
|
||||
priority: 2001,
|
||||
...(resource.ssl ? { tls } : {})
|
||||
};
|
||||
|
||||
// logger.info(`Maintenance mode active for ${fullDomain}`);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle path rewriting middleware
|
||||
if (
|
||||
@@ -608,29 +615,6 @@ export async function getTraefikConfig(
|
||||
}
|
||||
}
|
||||
|
||||
let rule = `Host(\`${fullDomain}\`)`;
|
||||
|
||||
// priority logic
|
||||
let priority: number;
|
||||
if (resource.priority && resource.priority != 100) {
|
||||
priority = resource.priority;
|
||||
} else {
|
||||
priority = 100;
|
||||
if (resource.path && resource.pathMatchType) {
|
||||
priority += 10;
|
||||
if (resource.pathMatchType === "exact") {
|
||||
priority += 5;
|
||||
} else if (resource.pathMatchType === "prefix") {
|
||||
priority += 3;
|
||||
} else if (resource.pathMatchType === "regex") {
|
||||
priority += 2;
|
||||
}
|
||||
if (resource.path === "/") {
|
||||
priority = 1; // lowest for catch-all
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.path && resource.pathMatchType) {
|
||||
//priority += 1;
|
||||
// add path to rule based on match type
|
||||
@@ -661,18 +645,6 @@ export async function getTraefikConfig(
|
||||
...(resource.ssl ? { tls } : {})
|
||||
};
|
||||
|
||||
if (resource.ssl) {
|
||||
config_output.http.routers![routerName + "-redirect"] = {
|
||||
entryPoints: [
|
||||
config.getRawConfig().traefik.http_entrypoint
|
||||
],
|
||||
middlewares: [redirectHttpsMiddlewareName],
|
||||
service: serviceName,
|
||||
rule: rule,
|
||||
priority: priority
|
||||
};
|
||||
}
|
||||
|
||||
config_output.http.services![serviceName] = {
|
||||
loadBalancer: {
|
||||
servers: (() => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Metadata } from "next";
|
||||
import { headers } from "next/headers";
|
||||
import { priv } from "@app/lib/api";
|
||||
import { GetMaintenanceInfoResponse } from "@server/routers/resource/types";
|
||||
@@ -10,9 +11,14 @@ import {
|
||||
} from "@app/components/ui/card";
|
||||
import { Alert, AlertTitle, AlertDescription } from "@app/components/ui/alert";
|
||||
import { Clock } from "lucide-react";
|
||||
import { AxiosResponse } from "axios";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Maintenance"
|
||||
};
|
||||
|
||||
export default async function MaintenanceScreen() {
|
||||
const t = await getTranslations();
|
||||
|
||||
@@ -25,12 +31,12 @@ export default async function MaintenanceScreen() {
|
||||
const host = headersList.get("host") || "";
|
||||
const hostname = host.split(":")[0];
|
||||
|
||||
const res = await priv.get<GetMaintenanceInfoResponse>(
|
||||
const res = await priv.get<AxiosResponse<GetMaintenanceInfoResponse>>(
|
||||
`/maintenance/info?fullDomain=${encodeURIComponent(hostname)}`
|
||||
);
|
||||
|
||||
if (res && res.status === 200) {
|
||||
const maintenanceInfo = res.data;
|
||||
const maintenanceInfo = res.data.data;
|
||||
title = maintenanceInfo?.maintenanceTitle || title;
|
||||
message = maintenanceInfo?.maintenanceMessage || message;
|
||||
estimatedTime = maintenanceInfo?.maintenanceEstimatedTime || null;
|
||||
|
||||
Reference in New Issue
Block a user