refactor(gateway): share host header parsing

This commit is contained in:
Peter Steinberger 2026-02-15 16:15:53 +00:00
parent 933a9945ae
commit 1843bcf1db
5 changed files with 24 additions and 56 deletions

View File

@ -14,6 +14,7 @@ import {
import {
isLoopbackAddress,
isTrustedProxyAddress,
resolveHostName,
parseForwardedForClientIp,
resolveGatewayClientIp,
} from "./net.js";
@ -56,21 +57,6 @@ function normalizeLogin(login: string): string {
return login.trim().toLowerCase();
}
function getHostName(hostHeader?: string): string {
const host = (hostHeader ?? "").trim().toLowerCase();
if (!host) {
return "";
}
if (host.startsWith("[")) {
const end = host.indexOf("]");
if (end !== -1) {
return host.slice(1, end);
}
}
const [name] = host.split(":");
return name ?? "";
}
function headerValue(value: string | string[] | undefined): string | undefined {
return Array.isArray(value) ? value[0] : value;
}
@ -107,7 +93,7 @@ export function isLocalDirectRequest(req?: IncomingMessage, trustedProxies?: str
return false;
}
const host = getHostName(req.headers?.host);
const host = resolveHostName(req.headers?.host);
const hostIsLocal = host === "localhost" || host === "127.0.0.1" || host === "::1";
const hostIsTailscaleServe = host.endsWith(".ts.net");

View File

@ -25,6 +25,25 @@ export function pickPrimaryLanIPv4(): string | undefined {
return undefined;
}
export function normalizeHostHeader(hostHeader?: string): string {
return (hostHeader ?? "").trim().toLowerCase();
}
export function resolveHostName(hostHeader?: string): string {
const host = normalizeHostHeader(hostHeader);
if (!host) {
return "";
}
if (host.startsWith("[")) {
const end = host.indexOf("]");
if (end !== -1) {
return host.slice(1, end);
}
}
const [name] = host.split(":");
return name ?? "";
}
export function isLoopbackAddress(ip: string | undefined): boolean {
if (!ip) {
return false;

View File

@ -1,26 +1,7 @@
import { isLoopbackHost } from "./net.js";
import { isLoopbackHost, normalizeHostHeader, resolveHostName } from "./net.js";
type OriginCheckResult = { ok: true } | { ok: false; reason: string };
function normalizeHostHeader(hostHeader?: string): string {
return (hostHeader ?? "").trim().toLowerCase();
}
function resolveHostName(hostHeader?: string): string {
const host = normalizeHostHeader(hostHeader);
if (!host) {
return "";
}
if (host.startsWith("[")) {
const end = host.indexOf("]");
if (end !== -1) {
return host.slice(1, end);
}
}
const [name] = host.split(":");
return name ?? "";
}
function parseOrigin(
originRaw?: string,
): { origin: string; host: string; hostname: string } | null {

View File

@ -4,21 +4,6 @@ import { GATEWAY_CLIENT_IDS } from "../../protocol/client-info.js";
export type AuthProvidedKind = "token" | "password" | "none";
export function resolveHostName(hostHeader?: string): string {
const host = (hostHeader ?? "").trim().toLowerCase();
if (!host) {
return "";
}
if (host.startsWith("[")) {
const end = host.indexOf("]");
if (end !== -1) {
return host.slice(1, end);
}
}
const [name] = host.split(":");
return name ?? "";
}
export function formatGatewayAuthFailureMessage(params: {
authMode: ResolvedGatewayAuth["mode"];
authProvided: AuthProvidedKind;

View File

@ -33,6 +33,7 @@ import {
import { authorizeGatewayConnect, isLocalDirectRequest } from "../../auth.js";
import { buildDeviceAuthPayload } from "../../device-auth.js";
import { isLoopbackAddress, isTrustedProxyAddress, resolveGatewayClientIp } from "../../net.js";
import { resolveHostName } from "../../net.js";
import { resolveNodeCommandAllowlist } from "../../node-command-policy.js";
import { checkBrowserOrigin } from "../../origin-check.js";
import { GATEWAY_CLIENT_IDS } from "../../protocol/client-info.js";
@ -58,11 +59,7 @@ import {
incrementPresenceVersion,
refreshGatewayHealthSnapshot,
} from "../health-state.js";
import {
formatGatewayAuthFailureMessage,
resolveHostName,
type AuthProvidedKind,
} from "./auth-messages.js";
import { formatGatewayAuthFailureMessage, type AuthProvidedKind } from "./auth-messages.js";
type SubsystemLogger = ReturnType<typeof createSubsystemLogger>;