Extract pure native request header helpers

This commit is contained in:
vorotamoroz committed 2026-11-04 02:09:00 +00:00
1 parent 8c51d66adf
commit 0e891998fd
3 files changed
+186 -76

No files matched your search

@@ -0,0 +1,84 @@
import { describe, expect, it } from "vitest";
import { createNativeRequestHeaders, shouldRevalidateNativeRequest } from "./nativeRequestHeaders";
describe("native cache revalidation decision", () => {
it.each(["GET", "HEAD", "get", "head"])("revalidates explicit no-cache/no-store for %s", (method) => {
expect(shouldRevalidateNativeRequest(method, "no-cache")).toBe(true);
expect(shouldRevalidateNativeRequest(method, "no-store")).toBe(true);
});
it.each([undefined, "default", "reload", "force-cache", "only-if-cached"] as const)(
"does not strengthen cache mode %s",
(mode) => {
expect(shouldRevalidateNativeRequest("GET", mode)).toBe(false);
expect(shouldRevalidateNativeRequest("HEAD", mode)).toBe(false);
}
);
it.each(["POST", "PUT", "PATCH", "DELETE", "OPTIONS"])("does not revalidate %s", (method) => {
expect(shouldRevalidateNativeRequest(method, "no-cache")).toBe(false);
expect(shouldRevalidateNativeRequest(method, "no-store")).toBe(false);
});
});
describe("native request header creation", () => {
it("copies input headers and removes the existing native-controlled header forms", () => {
const input = Object.freeze({
host: "first.test",
Host: "second.test",
"content-length": "1",
"Content-Length": "2",
Authorization: "Bearer fixture",
"Cache-Control": "max-age=60",
});
const result = createNativeRequestHeaders(input, "GET", "default");
expect(result).toEqual({ Authorization: "Bearer fixture", "Cache-Control": "max-age=60" });
expect(result).not.toBe(input);
expect(input.host).toBe("first.test");
expect(input["Content-Length"]).toBe("2");
});
it.each(["GET", "HEAD"])("creates no-store revalidation headers for %s", (method) => {
expect(createNativeRequestHeaders({}, method, "no-store")).toEqual({
"cache-control": "no-cache, no-store",
pragma: "no-cache",
});
});
it("preserves an existing no-store directive when enforcing no-cache", () => {
expect(
createNativeRequestHeaders(
{ "Cache-Control": "no-store, max-age=3600", Pragma: "legacy" },
"GET",
"no-cache"
)
).toEqual({ "Cache-Control": "no-store, no-cache", Pragma: "legacy, no-cache" });
});
it("combines differently cased header fields and retains non-conflicting directives", () => {
const input = Object.freeze({
"Cache-Control": 'Max-Age=99, no-transform, custom="a,b", No-Cache',
"cache-control": "max-stale=5, min-fresh=6, only-if-cached, NO-STORE, private",
Pragma: 'legacy="a,b", No-Cache',
pragma: "extension, no-cache",
});
expect(createNativeRequestHeaders(input, "get", "no-store")).toEqual({
"Cache-Control": 'no-transform, custom="a,b", private, no-cache, no-store',
Pragma: 'legacy="a,b", extension, no-cache',
});
expect(input["cache-control"]).toContain("max-stale=5");
});
it("does not split directive commas inside escaped quoted strings", () => {
const custom = String.raw`custom="a\"b,c"`;
expect(createNativeRequestHeaders({ "cache-control": `${custom}, max-age=1` }, "HEAD", "no-cache")).toEqual({
"cache-control": `${custom}, no-cache`,
pragma: "no-cache",
});
});
it("retains cache headers on a non-revalidated method", () => {
const headers = { "cache-control": "max-age=99", Pragma: "legacy" };
expect(createNativeRequestHeaders(headers, "POST", "no-store")).toEqual(headers);
});
});