From 4a381ef3ad74144f871d978d4898298a2297c8c6 Mon Sep 17 00:00:00 2001 From: vagdotdev Date: Tue, 30 Jun 2026 13:47:22 +0530 Subject: [PATCH] fix: normalize file proxy patterns --- lib/db/db-client.ts | 20 +++++++++++++++++--- tests/routes/file-proxy01.test.ts | 30 ++++++++++++++++++++++++++++++ tests/routes/file-proxy04.test.ts | 6 +++--- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/lib/db/db-client.ts b/lib/db/db-client.ts index 977b5dd..ab5f7d4 100644 --- a/lib/db/db-client.ts +++ b/lib/db/db-client.ts @@ -213,9 +213,13 @@ const initializer = combine(databaseSchema.parse({}), (set, get) => ({ proxy: Omit, ): FileProxy => { let newProxy: FileProxy + const normalizedProxy = { + ...proxy, + matching_pattern: normalizeMatchingPattern(proxy.matching_pattern), + } set((state) => { newProxy = { - ...proxy, + ...normalizedProxy, file_proxy_id: state.idCounter.toString(), created_at: new Date().toISOString(), } as FileProxy @@ -232,11 +236,13 @@ const initializer = combine(databaseSchema.parse({}), (set, get) => ({ matching_pattern?: string }): FileProxy | undefined => { const state = get() + const matchingPattern = query.matching_pattern + ? normalizeMatchingPattern(query.matching_pattern) + : undefined return state.file_proxies.find( (p) => (query.file_proxy_id && p.file_proxy_id === query.file_proxy_id) || - (query.matching_pattern && - p.matching_pattern === query.matching_pattern), + (matchingPattern && p.matching_pattern === matchingPattern), ) }, @@ -261,3 +267,11 @@ const initializer = combine(databaseSchema.parse({}), (set, get) => ({ return undefined }, })) + +function normalizeMatchingPattern(matching_pattern: string): string { + if (!matching_pattern.endsWith("/*")) { + return normalizePath(matching_pattern) + } + + return `${normalizePath(matching_pattern.slice(0, -2))}/*` +} diff --git a/tests/routes/file-proxy01.test.ts b/tests/routes/file-proxy01.test.ts index a3cd999..0dbe91c 100644 --- a/tests/routes/file-proxy01.test.ts +++ b/tests/routes/file-proxy01.test.ts @@ -93,3 +93,33 @@ test("file proxy create validation - duplicate pattern", async () => { status: 400, }) }) + +test("file proxy patterns normalize leading slashes for lookup and duplicates", async () => { + const { axios } = await getTestServer() + + const createRes = await axios.post("/file_proxies/create", { + proxy_type: "disk", + disk_path: "/tmp/test", + matching_pattern: "/normalized/*", + }) + expect(createRes.status).toBe(200) + expect(createRes.data.file_proxy.matching_pattern).toBe("normalized/*") + + const getWithLeadingSlash = await axios.get("/file_proxies/get", { + params: { matching_pattern: "/normalized/*" }, + }) + expect(getWithLeadingSlash.status).toBe(200) + expect(getWithLeadingSlash.data.file_proxy.file_proxy_id).toBe( + createRes.data.file_proxy.file_proxy_id, + ) + + await expect( + axios.post("/file_proxies/create", { + proxy_type: "http", + http_target_url: "https://example.com", + matching_pattern: "normalized/*", + }), + ).rejects.toMatchObject({ + status: 400, + }) +}) diff --git a/tests/routes/file-proxy04.test.ts b/tests/routes/file-proxy04.test.ts index 4fae9de..238e0da 100644 --- a/tests/routes/file-proxy04.test.ts +++ b/tests/routes/file-proxy04.test.ts @@ -149,14 +149,14 @@ test("proxy pattern with leading slash normalization", async () => { try { await writeFile(join(tempDir, "normalized.txt"), "Normalized path content") - // Create proxy with pattern (without leading slash in pattern) + // Create proxy with a leading slash in the pattern await axios.post("/file_proxies/create", { proxy_type: "disk", disk_path: tempDir, - matching_pattern: "slash-test/*", + matching_pattern: "/slash-test/*", }) - // Should work with leading slash in the request path + // Should normalize the proxy pattern and match the request path const res = await axios.get("/files/download/slash-test/normalized.txt") expect(res.status).toBe(200) expect(res.data).toBe("Normalized path content")