Skip to content

Commit cbddce3

Browse files
committed
Make cache-control enforcement unconditional in addCacheControlHeadersForSession
1 parent f475344 commit cbddce3

File tree

2 files changed

+14
-72
lines changed

2 files changed

+14
-72
lines changed

src/server/cookies.test.ts

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,9 @@ describe("encrypt/decrypt", async () => {
5656
});
5757

5858
describe("addCacheControlHeadersForSession", () => {
59-
it("adds cache headers if __session cookie has a future Date expiry", () => {
59+
it("unconditionally adds strict cache headers", () => {
6060
const res = NextResponse.next();
61-
const futureDate = new Date(Date.now() + 60_000); // 1 minute in the future
6261

63-
res.cookies.set("__session", "dummy", { expires: futureDate });
6462
addCacheControlHeadersForSession(res);
6563

6664
expect(res.headers.get("Cache-Control")).toBe(
@@ -69,43 +67,4 @@ describe("addCacheControlHeadersForSession", () => {
6967
expect(res.headers.get("Pragma")).toBe("no-cache");
7068
expect(res.headers.get("Expires")).toBe("0");
7169
});
72-
73-
it("does NOT add headers if __session cookie is missing", () => {
74-
const res = NextResponse.next();
75-
76-
addCacheControlHeadersForSession(res);
77-
expect(res.headers.get("Cache-Control")).toBeNull();
78-
expect(res.headers.get("Pragma")).toBeNull();
79-
expect(res.headers.get("Expires")).toBeNull();
80-
});
81-
82-
it("does NOT add headers if __session cookie is expired", () => {
83-
const res = NextResponse.next();
84-
const pastDate = new Date(Date.now() - 60_000); // 1 minute in the past
85-
86-
res.cookies.set("__session", "dummy", { expires: pastDate });
87-
addCacheControlHeadersForSession(res);
88-
89-
expect(res.headers.get("Cache-Control")).toBeNull();
90-
});
91-
92-
it("does NOT add headers if __session cookie has no value", () => {
93-
const res = NextResponse.next();
94-
const futureDate = new Date(Date.now() + 60_000);
95-
96-
// setting an empty value simulates a session cookie being cleared
97-
res.cookies.set("__session", "", { expires: futureDate });
98-
addCacheControlHeadersForSession(res);
99-
100-
expect(res.headers.get("Cache-Control")).toBeNull();
101-
});
102-
103-
it("does NOT add headers if __session cookie has no expires field", () => {
104-
const res = NextResponse.next();
105-
106-
res.cookies.set("__session", "dummy"); // no `expires`
107-
addCacheControlHeadersForSession(res);
108-
109-
expect(res.headers.get("Cache-Control")).toBeNull();
110-
});
11170
});

src/server/cookies.ts

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -332,37 +332,20 @@ export function deleteChunkedCookie(
332332
}
333333

334334
/**
335-
* Returns true if the cookie's `expires` field represents a future time.
336-
* Handles both Date objects and numeric UNIX timestamps.
337-
*/
338-
function isValidFutureExpiry(expires: Date | number): boolean {
339-
const now = Date.now();
340-
return typeof expires === "number"
341-
? expires * 1000 > now
342-
: expires instanceof Date && expires.getTime() > now;
343-
}
344-
345-
/**
346-
* Adds strict cache-control headers to prevent shared CDN caching of
347-
* responses that contain a valid `Set-Cookie: __session`.
335+
* Unconditionally adds strict cache-control headers to the response.
336+
*
337+
* This ensures the response is not cached by CDNs or other shared caches.
338+
* It is now the caller's responsibility to decide when to call this function.
348339
*
349-
* Only applies headers if a future-expiring `__session` cookie is present
350-
* in the response — avoiding overly aggressive cache disabling.
340+
* Usage:
341+
* Call this function whenever a `Set-Cookie` header is being written
342+
* for session management or any other sensitive data that must not be cached.
351343
*/
352344
export function addCacheControlHeadersForSession(res: NextResponse): void {
353-
const sessionCookie = res.cookies.get("__session");
354-
355-
const isFreshCookie =
356-
sessionCookie?.value &&
357-
sessionCookie?.expires &&
358-
isValidFutureExpiry(sessionCookie.expires);
359-
360-
if (isFreshCookie) {
361-
res.headers.set(
362-
"Cache-Control",
363-
"private, no-cache, no-store, must-revalidate, max-age=0"
364-
);
365-
res.headers.set("Pragma", "no-cache");
366-
res.headers.set("Expires", "0");
367-
}
345+
res.headers.set(
346+
"Cache-Control",
347+
"private, no-cache, no-store, must-revalidate, max-age=0"
348+
);
349+
res.headers.set("Pragma", "no-cache");
350+
res.headers.set("Expires", "0");
368351
}

0 commit comments

Comments
 (0)