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.
This commit is contained in:
1 parent
ef049b6521
commit
517139cbf4
2 files changed
+28
-5
No files matched your search
@@ -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<string, CustomDomainCorsCacheEntry>();
|
||||
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user