From 517139cbf48283af1c9573ca7acf2cfc62bcfcc4 Mon Sep 17 00:00:00 2001 From: Ian Troisi <56521951+Cincinnatus101010@users.noreply.github.com> Date: Thu, 11 Jun 2026 14:48:31 -0400 Subject: [PATCH] fix: cache negative custom domain CORS lookups Use a shorter TTL for rejected origins so unknown domains do not hit the database on every cross-origin request. --- .../api/middleware/statusPageCorsOrigin.ts | 19 ++++++++++++++----- .../middleware/statusPageCorsOrigin.test.ts | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/server/src/api/middleware/statusPageCorsOrigin.ts b/server/src/api/middleware/statusPageCorsOrigin.ts index acc515bf9..338c43472 100644 --- a/server/src/api/middleware/statusPageCorsOrigin.ts +++ b/server/src/api/middleware/statusPageCorsOrigin.ts @@ -2,16 +2,27 @@ import type { CorsOptions } from "cors"; import type { IStatusPagesRepository } from "@/domain/status-pages/status-page-repository.interface.js"; import { normalizeStatusPageDomain } from "@/utils/statusPageDomain.js"; -const CUSTOM_DOMAIN_CORS_CACHE_TTL_MS = 5 * 60 * 1000; +const CUSTOM_DOMAIN_CORS_POSITIVE_CACHE_TTL_MS = 5 * 60 * 1000; +const CUSTOM_DOMAIN_CORS_NEGATIVE_CACHE_TTL_MS = 60 * 1000; type CustomDomainCorsCacheEntry = { allowed: boolean; expiresAt: number; }; +const getCustomDomainCorsCacheTtlMs = (allowed: boolean): number => + allowed ? CUSTOM_DOMAIN_CORS_POSITIVE_CACHE_TTL_MS : CUSTOM_DOMAIN_CORS_NEGATIVE_CACHE_TTL_MS; + export const createStatusPageCorsOrigin = (clientHost: string, statusPagesRepository: IStatusPagesRepository): CorsOptions["origin"] => { const cache = new Map(); + const cacheOriginResult = (customDomain: string, allowed: boolean) => { + cache.set(customDomain, { + allowed, + expiresAt: Date.now() + getCustomDomainCorsCacheTtlMs(allowed), + }); + }; + return (origin, callback) => { if (!origin) { callback(null, true); @@ -46,13 +57,11 @@ export const createStatusPageCorsOrigin = (clientHost: string, statusPagesReposi .findByCustomDomain(customDomain) .then((statusPage) => { const allowed = statusPage.isPublished; - cache.set(customDomain, { - allowed, - expiresAt: Date.now() + CUSTOM_DOMAIN_CORS_CACHE_TTL_MS, - }); + cacheOriginResult(customDomain, allowed); callback(null, allowed ? origin : false); }) .catch(() => { + cacheOriginResult(customDomain, false); callback(null, false); }); }; diff --git a/server/test/unit/middleware/statusPageCorsOrigin.test.ts b/server/test/unit/middleware/statusPageCorsOrigin.test.ts index b0f92cac4..88a854845 100644 --- a/server/test/unit/middleware/statusPageCorsOrigin.test.ts +++ b/server/test/unit/middleware/statusPageCorsOrigin.test.ts @@ -56,5 +56,19 @@ describe("createStatusPageCorsOrigin", () => { const originFn = createStatusPageCorsOrigin("https://checkmate.example.com", repo as IStatusPagesRepository); await expect(invokeOrigin(originFn, "https://status.example.com")).resolves.toBe(false); + await expect(invokeOrigin(originFn, "https://status.example.com")).resolves.toBe(false); + + expect(repo.findByCustomDomain).toHaveBeenCalledTimes(1); + }); + + it("caches unknown custom domain lookups", async () => { + repo.findByCustomDomain.mockRejectedValue(new Error("Status page not found")); + const originFn = createStatusPageCorsOrigin("https://checkmate.example.com", repo as IStatusPagesRepository); + + await expect(invokeOrigin(originFn, "https://unknown.example.com")).resolves.toBe(false); + await expect(invokeOrigin(originFn, "https://unknown.example.com")).resolves.toBe(false); + + expect(repo.findByCustomDomain).toHaveBeenCalledTimes(1); + expect(repo.findByCustomDomain).toHaveBeenCalledWith("unknown.example.com"); }); });