Skip to content

Commit 49c4be1

Browse files
SebF33bartlomieju
andauthored
fix: handle commas in static file paths (#3770)
After #3659, static file handling correctly supports spaces and encoded paths, but filenames containing commas are not resolved. Example: - File: `foo,bar.css` - Stored in cache as: `/foo%2Cbar.css` - Request: `/foo,bar.css` --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
1 parent ecc4285 commit 49c4be1

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

packages/fresh/src/middlewares/static_files.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ import { BUILD_ID } from "@fresh/build-id";
44
import { tracer } from "../otel.ts";
55
import { getBuildCache } from "../context.ts";
66

7+
/** Decode and re-encode each path segment so that characters like commas
8+
* are percent-encoded consistently with how `prepareStaticFile` stores
9+
* entries in the build cache. */
10+
function normalizePathname(pathname: string): string {
11+
return "/" +
12+
pathname.split("/").filter(Boolean).map(encodeURIComponent).join("/");
13+
}
14+
715
/**
816
* Fresh middleware to serve static files from the `static/` directory.
917
* ```ts
@@ -25,6 +33,13 @@ export function staticFiles<T>(): Middleware<T> {
2533
: "/";
2634
}
2735

36+
try {
37+
pathname = normalizePathname(decodeURIComponent(pathname));
38+
} catch (_e: unknown) {
39+
if (!(_e instanceof URIError)) throw _e;
40+
return await ctx.next();
41+
}
42+
2843
// Fast path bail out
2944
const startTime = performance.now() + performance.timeOrigin;
3045
const file = await buildCache.readFile(pathname);

packages/fresh/src/middlewares/static_files_test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,3 +296,29 @@ Deno.test("static files - fallthrough", async () => {
296296
expect(text).toEqual("it works");
297297
expect(called).toEqual(["before", "after"]);
298298
});
299+
300+
Deno.test("static files - comma in pathname", async () => {
301+
const key = systemPathToUrlEncoded("foo,bar.css");
302+
303+
const buildCache = new MockBuildCache({
304+
[key]: {
305+
content: "body {}",
306+
hash: null,
307+
},
308+
});
309+
310+
const server = serveMiddleware(
311+
staticFiles(),
312+
{ buildCache },
313+
);
314+
315+
// Browser/request path usually keeps the comma unencoded
316+
let res = await server.get("/foo,bar.css");
317+
await res.body?.cancel();
318+
expect(res.status).toEqual(200);
319+
320+
// Encoded form should also resolve
321+
res = await server.get("/foo%2Cbar.css");
322+
await res.body?.cancel();
323+
expect(res.status).toEqual(200);
324+
});

0 commit comments

Comments
 (0)