Skip to content
File

Blob: src/worker/routes/host.ts

typescript60 lines
1import { isValidHostLabel } from "@/worker/auth/host-labels";
2import type { HostInfo } from "@/worker/types";
3 
4function stripPort(host: string): string {
5 if (host.startsWith("[")) {
6 const end = host.indexOf("]");
7 return end === -1 ? host : host.slice(0, end + 1);
8 }
9 
10 const colon = host.lastIndexOf(":");
11 if (colon === -1) return host;
12 return host.slice(0, colon);
13}
14 
15export function normalizeHostHeader(hostHeader: string | null): string {
16 if (!hostHeader) return "";
17 const withoutPort = stripPort(hostHeader.trim());
18 const withoutTrailingDot = withoutPort.endsWith(".") ? withoutPort.slice(0, -1) : withoutPort;
19 return withoutTrailingDot.toLowerCase();
20}
21 
22export function classifyHost(request: Request, env: Env): HostInfo {
23 const controlPlaneHost = env.CONTROL_PLANE_HOST.toLowerCase();
24 const subjectHostSuffix = env.SUBJECT_HOST_SUFFIX.toLowerCase();
25 const originalHost = request.headers.get("host") ?? new URL(request.url).host;
26 const normalizedHost = normalizeHostHeader(originalHost);
27 
28 if (normalizedHost === controlPlaneHost) {
29 return {
30 kind: "control",
31 originalHost,
32 normalizedHost,
33 controlPlaneHost,
34 subjectHostSuffix,
35 };
36 }
37 
38 if (normalizedHost.endsWith(subjectHostSuffix)) {
39 const hostLabel = normalizedHost.slice(0, -subjectHostSuffix.length);
40 if (isValidHostLabel(hostLabel)) {
41 return {
42 kind: "subject",
43 originalHost,
44 normalizedHost,
45 controlPlaneHost,
46 subjectHostSuffix,
47 hostLabel,
48 };
49 }
50 }
51 
52 return {
53 kind: "unknown",
54 originalHost,
55 normalizedHost,
56 controlPlaneHost,
57 subjectHostSuffix,
58 };
59}