perf: cache custom domain CORS origin lookups
Avoid hitting the database on every cross-origin request by caching published custom domain checks for five minutes.
This commit is contained in:
1 parent
6a1ab622b3
commit
120708ed47
2 files changed
+81
-1
No files matched your search
@@ -2,7 +2,16 @@ 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;
|
||||
|
||||
type CustomDomainCorsCacheEntry = {
|
||||
allowed: boolean;
|
||||
expiresAt: number;
|
||||
};
|
||||
|
||||
export const createStatusPageCorsOrigin = (clientHost: string, statusPagesRepository: IStatusPagesRepository): CorsOptions["origin"] => {
|
||||
const cache = new Map<string, CustomDomainCorsCacheEntry>();
|
||||
|
||||
return (origin, callback) => {
|
||||
if (!origin) {
|
||||
callback(null, true);
|
||||
@@ -27,10 +36,21 @@ export const createStatusPageCorsOrigin = (clientHost: string, statusPagesReposi
|
||||
return;
|
||||
}
|
||||
|
||||
const cached = cache.get(customDomain);
|
||||
if (cached && cached.expiresAt > Date.now()) {
|
||||
callback(null, cached.allowed ? origin : false);
|
||||
return;
|
||||
}
|
||||
|
||||
statusPagesRepository
|
||||
.findByCustomDomain(customDomain)
|
||||
.then((statusPage) => {
|
||||
callback(null, statusPage.isPublished ? origin : false);
|
||||
const allowed = statusPage.isPublished;
|
||||
cache.set(customDomain, {
|
||||
allowed,
|
||||
expiresAt: Date.now() + CUSTOM_DOMAIN_CORS_CACHE_TTL_MS,
|
||||
});
|
||||
callback(null, allowed ? origin : false);
|
||||
})
|
||||
.catch(() => {
|
||||
callback(null, false);
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { describe, expect, it, jest, beforeEach } from "@jest/globals";
|
||||
import { createStatusPageCorsOrigin } from "../../../src/api/middleware/statusPageCorsOrigin.ts";
|
||||
import type { IStatusPagesRepository } from "../../../src/domain/status-pages/status-page-repository.interface.ts";
|
||||
import type { StatusPage } from "../../../src/domain/status-pages/status-page.type.ts";
|
||||
|
||||
const makeStatusPage = (overrides?: Partial<StatusPage>): StatusPage =>
|
||||
({
|
||||
id: "sp-1",
|
||||
isPublished: true,
|
||||
customDomain: "status.example.com",
|
||||
...overrides,
|
||||
}) as StatusPage;
|
||||
|
||||
const createRepo = () =>
|
||||
({
|
||||
findByCustomDomain: jest.fn().mockResolvedValue(makeStatusPage()),
|
||||
}) as unknown as jest.Mocked<Pick<IStatusPagesRepository, "findByCustomDomain">>;
|
||||
|
||||
const invokeOrigin = (originFn: ReturnType<typeof createStatusPageCorsOrigin>, origin: string): Promise<boolean | string> =>
|
||||
new Promise((resolve, reject) => {
|
||||
originFn?.(origin, (error, result) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(result ?? false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createStatusPageCorsOrigin", () => {
|
||||
let repo: jest.Mocked<Pick<IStatusPagesRepository, "findByCustomDomain">>;
|
||||
|
||||
beforeEach(() => {
|
||||
repo = createRepo();
|
||||
});
|
||||
|
||||
it("allows the configured client host without a repository lookup", async () => {
|
||||
const originFn = createStatusPageCorsOrigin("https://checkmate.example.com", repo as IStatusPagesRepository);
|
||||
|
||||
await expect(invokeOrigin(originFn, "https://checkmate.example.com")).resolves.toBe(true);
|
||||
expect(repo.findByCustomDomain).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("caches published custom domain lookups", async () => {
|
||||
const originFn = createStatusPageCorsOrigin("https://checkmate.example.com", repo as IStatusPagesRepository);
|
||||
|
||||
await expect(invokeOrigin(originFn, "https://status.example.com")).resolves.toBe("https://status.example.com");
|
||||
await expect(invokeOrigin(originFn, "https://status.example.com")).resolves.toBe("https://status.example.com");
|
||||
|
||||
expect(repo.findByCustomDomain).toHaveBeenCalledTimes(1);
|
||||
expect(repo.findByCustomDomain).toHaveBeenCalledWith("status.example.com");
|
||||
});
|
||||
|
||||
it("rejects unpublished custom domains", async () => {
|
||||
repo.findByCustomDomain.mockResolvedValue(makeStatusPage({ isPublished: false }));
|
||||
const originFn = createStatusPageCorsOrigin("https://checkmate.example.com", repo as IStatusPagesRepository);
|
||||
|
||||
await expect(invokeOrigin(originFn, "https://status.example.com")).resolves.toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user