Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions packages/fresh/src/middlewares/static_files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,20 @@ export function staticFiles<T>(): Middleware<T> {
vary: "If-None-Match",
});

const ifNoneMatch = req.headers.get("If-None-Match");
if (
ifNoneMatch !== null &&
(ifNoneMatch === etag || ifNoneMatch === `W/"${etag}"`)
) {
file.close();
span.setAttribute("fresh.cache", "not_modified");
return new Response(null, { status: 304, headers });
} else if (etag !== null) {
headers.set("Etag", `W/"${etag}"`);
// In development mode, skip ETag validation to prevent serving stale
// cached assets when switching between different apps on the same port
if (ctx.config.mode !== "development") {
const ifNoneMatch = req.headers.get("If-None-Match");
if (
ifNoneMatch !== null &&
(ifNoneMatch === etag || ifNoneMatch === `W/"${etag}"`)
) {
file.close();
span.setAttribute("fresh.cache", "not_modified");
return new Response(null, { status: 304, headers });
} else if (etag !== null) {
headers.set("Etag", `W/"${etag}"`);
}
}

if (
Expand Down
40 changes: 38 additions & 2 deletions packages/fresh/src/middlewares/static_files_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,20 @@ Deno.test("static files - HEAD 200", async () => {
expect(content).toEqual("");
});

Deno.test("static files - etag", async () => {
Deno.test("static files - etag in production", async () => {
const buildCache = new MockBuildCache({
"foo.css": { content: "body {}", hash: "123" },
});
const server = serveMiddleware(
staticFiles(),
{ buildCache },
{
buildCache,
config: {
root: "",
basePath: "",
mode: "production",
},
},
);

const cacheUrl = `/foo.css?${ASSET_CACHE_BUST_KEY}=${BUILD_ID}`;
Expand All @@ -111,6 +118,35 @@ Deno.test("static files - etag", async () => {
expect(res.status).toEqual(304);
});

Deno.test("static files - no etag in development", async () => {
const buildCache = new MockBuildCache({
"foo.css": { content: "body {}", hash: "123" },
});
const server = serveMiddleware(
staticFiles(),
{
buildCache,
config: {
root: "",
basePath: "",
mode: "development",
},
},
);

const cacheUrl = `/foo.css`;
let res = await server.get(cacheUrl);
await res.body?.cancel();
expect(res.headers.get("Etag")).toBeNull();

// Even if client sends If-None-Match in dev mode, always return 200
const headers = new Headers();
headers.append("If-None-Match", "123");
res = await server.get(cacheUrl, { headers });
await res.body?.cancel();
expect(res.status).toEqual(200);
});

Deno.test("static files - 404 on missing favicon.ico", async () => {
const buildCache = new MockBuildCache({});
const server = serveMiddleware(
Expand Down
Loading