Use p host to pass the host header

This commit is contained in:
Owen
2026-08-04 16:55:39 -04:00
parent aad26b9ae4
commit 36c0edc62e
2 changed files with 47 additions and 6 deletions
+42 -5
View File
@@ -1548,6 +1548,20 @@ export async function getTraefikConfig(
} }
if (aiGatewayUrl) { if (aiGatewayUrl) {
// The AI gateway may live on a different host than the inference
// resource itself (e.g. a remote exit node forwarding to the
// central dashboard over a tunnel). passHostHeader would forward
// the resource's own Host, which that external host won't
// recognize, so we pin the Host header to the gateway's own host
// and smuggle the original resource host through in "p-host"
// instead (same pattern as the maintenance-page routes above).
let aiGatewayHost: string | undefined;
try {
aiGatewayHost = new URL(aiGatewayUrl).host;
} catch {
aiGatewayHost = undefined;
}
// Public inference resources: same TLS/cert-resolver handling as // Public inference resources: same TLS/cert-resolver handling as
// plain http-mode resources, but the service points at the AI // plain http-mode resources, but the service points at the AI
// gateway instead of any real backend targets. // gateway instead of any real backend targets.
@@ -1613,10 +1627,21 @@ export async function getTraefikConfig(
} }
} }
const irHeadersMiddlewareName = `${irKey}-headers-middleware`;
config_output.http.middlewares[irHeadersMiddlewareName] = {
headers: {
customRequestHeaders: {
...(aiGatewayHost ? { Host: aiGatewayHost } : {}),
"p-host": fullDomain
}
}
};
const additionalMiddlewares = const additionalMiddlewares =
config.getRawConfig().traefik.additional_middlewares || []; config.getRawConfig().traefik.additional_middlewares || [];
const routerMiddlewares = [ const routerMiddlewares = [
badgerMiddlewareName, badgerMiddlewareName,
irHeadersMiddlewareName,
...additionalMiddlewares ...additionalMiddlewares
]; ];
@@ -1647,8 +1672,7 @@ export async function getTraefikConfig(
config_output.http.services[serviceName] = { config_output.http.services[serviceName] = {
loadBalancer: { loadBalancer: {
servers: [{ url: `${aiGatewayUrl}/chat/completions` }], servers: [{ url: `${aiGatewayUrl}/chat/completions` }]
passHostHeader: true
} }
}; };
} }
@@ -1701,8 +1725,22 @@ export async function getTraefikConfig(
} }
} }
const srHeadersMiddlewareName = `${srKey}-headers-middleware`;
config_output.http.middlewares[srHeadersMiddlewareName] = {
headers: {
customRequestHeaders: {
...(aiGatewayHost ? { Host: aiGatewayHost } : {}),
"p-host": alias
}
}
};
const additionalMiddlewares = const additionalMiddlewares =
config.getRawConfig().traefik.additional_middlewares || []; config.getRawConfig().traefik.additional_middlewares || [];
const routerMiddlewares = [
srHeadersMiddlewareName,
...additionalMiddlewares
];
if (sr.ssl) { if (sr.ssl) {
config_output.http.routers[routerName + "-redirect"] = { config_output.http.routers[routerName + "-redirect"] = {
@@ -1722,7 +1760,7 @@ export async function getTraefikConfig(
? config.getRawConfig().traefik.https_entrypoint ? config.getRawConfig().traefik.https_entrypoint
: config.getRawConfig().traefik.http_entrypoint : config.getRawConfig().traefik.http_entrypoint
], ],
middlewares: additionalMiddlewares, middlewares: routerMiddlewares,
service: serviceName, service: serviceName,
rule, rule,
priority: 100, priority: 100,
@@ -1731,8 +1769,7 @@ export async function getTraefikConfig(
config_output.http.services[serviceName] = { config_output.http.services[serviceName] = {
loadBalancer: { loadBalancer: {
servers: [{ url: `${aiGatewayUrl}/chat/completions` }], servers: [{ url: `${aiGatewayUrl}/chat/completions` }]
passHostHeader: true
} }
}; };
} }
+5 -1
View File
@@ -416,7 +416,11 @@ export async function chatCompletions(
res: Response res: Response
): Promise<any> { ): Promise<any> {
try { try {
const host = (req.headers.host || "").split(":")[0]; const host = (
(req.headers["p-host"] as string | undefined) ||
req.headers.host ||
""
).split(":")[0];
if (!host) { if (!host) {
return res return res
.status(HttpCode.BAD_REQUEST) .status(HttpCode.BAD_REQUEST)