Skip to content

Commit

Permalink
better headers
Browse files Browse the repository at this point in the history
  • Loading branch information
nichtsam committed Jul 3, 2024
1 parent efc8bd2 commit 3c70abb
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 12 deletions.
53 changes: 53 additions & 0 deletions app/utils/remix.server.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { describe, expect, test } from "vitest";
import { getConservativeCacheControl } from "./remix.server";
import cacheControl from "cache-control-parser";

describe("getConservativeCacheControl", () => {
test("it works for basic usecase", () => {
const result = getConservativeCacheControl(
"max-age=3600",
"max-age=1800, s-maxage=600",
"private, max-age=86400",
);

expect(result).toEqual(
cacheControl.stringify({
"max-age": 1800,
"s-maxage": 600,
private: true,
}),
);
});
test("retains boolean directive", () => {
const result = cacheControl.parse(
getConservativeCacheControl("private", "no-cache,no-store"),
);

expect(result.private).toEqual(true);
expect(result["no-cache"]).toEqual(true);
expect(result["no-store"]).toEqual(true);
});
test("get shortest number directive", () => {
const result = cacheControl.parse(
getConservativeCacheControl(
"max-age=10, s-maxage=300",
"max-age=300, s-maxage=600",
),
);

expect(result["max-age"]).toEqual(10);
expect(result["s-maxage"]).toEqual(300);
});
test("lets unset directives remain unset", () => {
const result = cacheControl.parse(
getConservativeCacheControl(
"max-age=3600",
"max-age=1800, s-maxage=600",
"private, max-age=86400",
),
);

expect(result["must-revalidate"]).toBeUndefined();
expect(result["stale-while-revalidate"]).toBeUndefined();
});
});
40 changes: 28 additions & 12 deletions app/utils/remix.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,44 @@ export function pipeHeaders({
return headers;
}

function getConservativeCacheControl(
export function getConservativeCacheControl(
...cacheControlHeaders: Array<string | null>
): string {
return cacheControl.stringify(
cacheControlHeaders
.filter(Boolean)
.map((header) => cacheControl.parse(header))
.reduce<CacheControl>((final, current) => {
if (current.private) {
final.private = true;
}
.reduce<CacheControl>((acc, current) => {
let directive: keyof CacheControl;
for (directive in current) {
const currentValue = current[directive];

switch (typeof currentValue) {
case "boolean": {
if (currentValue) {
// @ts-expect-error
acc[directive] = true;
}
break;
}
case "number": {
const accValue = acc[directive] as number;

const finalMaxAge = final["max-age"];
const currentMaxAge = current["max-age"];
if (accValue !== undefined && currentValue !== undefined) {
const result = Math.min(accValue, currentValue);
// @ts-expect-error
acc[directive] = result;
} else if (accValue === undefined) {
// @ts-expect-error
acc[directive] = currentValue;
}

if (finalMaxAge !== undefined && currentMaxAge !== undefined) {
final["max-age"] = Math.min(finalMaxAge, currentMaxAge);
} else if (finalMaxAge === undefined) {
final["max-age"] = currentMaxAge;
break;
}
}
}

return final;
return acc;
}, {}),
);
}

0 comments on commit 3c70abb

Please sign in to comment.