104 lines · 4.6 KB
import { env } from "cloudflare:workers";
import { enforceRateLimit, requestIp } from "../limits";
import { HttpError } from "../errors";
import { customHostKey, isForgeHostname, metaKey, sitesDomain, slotKey } from "./config";
import { hostLabel } from "./naming";
import { accessSubject, challenge, handleAccessRoute } from "./access";
import { runSiteWorker } from "./runtime";
import { loadManifest, plain } from "./static";
import { handleAbuseReport, handleScratchUpload } from "./scratch";
import { meteredResponse } from "./usage";
import { scratchWithinQuota } from "./metering";
import type { SiteMeta, SlotPointer } from "./config";

const POINTER_CACHE_SECONDS = 30;
const REPORT_PATH = "/__gitfor/report";
const UNMETERED = new WeakSet<Response>();

type Resolved = { label: string; pointer: SlotPointer; meta: SiteMeta };

function pointer(label: string): Promise<SlotPointer | null> {
  return env.KV.get<SlotPointer>(slotKey(label), { type: "json", cacheTtl: POINTER_CACHE_SECONDS });
}

function meta(siteId: string): Promise<SiteMeta | null> {
  return env.KV.get<SiteMeta>(metaKey(siteId), { type: "json", cacheTtl: POINTER_CACHE_SECONDS });
}

/** Maps a request host to the site and deployment it serves; custom domains only after verification wrote KV. */
export async function resolveSiteHost(hostname: string): Promise<Resolved | null> {
  const domain = sitesDomain();
  if (!domain) return null;
  let label = hostLabel(hostname, domain);
  if (!label) {
    const custom = await env.KV.get<{ siteId: string; label: string }>(customHostKey(hostname), {
      type: "json",
      cacheTtl: POINTER_CACHE_SECONDS,
    });
    if (!custom) return null;
    label = custom.label;
  }