| 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; |
| 3 | import { archivedAssetKey, serveArchivedAsset } from "./asset-archive.ts"; |
| 4 | |
| 5 | test("archive keys cannot read releases, source maps or private objects", () => { |
| 6 | assert.equal(archivedAssetKey("/assets/app-old12345.css"), "web-assets/assets/app-old12345.css"); |
| 7 | for (const path of ["/downloads/runner", "/assets/../secret.js", "/assets/a.js.map", "/assets/%2e%2e/secret.js", "/assets/nested/a.js"]) assert.equal(archivedAssetKey(path), null); |
| 8 | }); |
| 9 | |
| 10 | test("a stylesheet removed from the new build stays available with its MIME type", async () => { |
| 11 | const bucket = { get: async (key: string) => { |
| 12 | assert.equal(key, "web-assets/assets/app-old12345.css"); |
| 13 | return { body: "body{color:red}", size: 15, httpEtag: '"old"', writeHttpMetadata: (headers: Headers) => headers.set("content-type", "text/css") }; |
| 14 | } } as unknown as R2Bucket; |
| 15 | const url = "https://g1t.sh/assets/app-old12345.css"; |
| 16 | const response = await serveArchivedAsset(new Request(url), bucket); |
| 17 | assert.equal(response.status, 200); |
| 18 | assert.equal(response.headers.get("content-type"), "text/css"); |
| 19 | assert.match(response.headers.get("cache-control")!, /immutable/); |
| 20 | assert.equal(await response.text(), "body{color:red}"); |
| 21 | assert.equal(await (await serveArchivedAsset(new Request(url, { method: "HEAD" }), bucket)).text(), ""); |
| 22 | assert.equal((await serveArchivedAsset(new Request(url, { headers: { "if-none-match": '"old"' } }), bucket)).status, 304); |
| 23 | }); |
| 24 | |
| 25 | test("missing or unavailable assets never become HTML or cacheable errors", async () => { |
| 26 | const url = "https://g1t.sh/assets/missing-12345678.js"; |
| 27 | const missing = await serveArchivedAsset(new Request(url), { get: async () => null } as unknown as R2Bucket); |
| 28 | assert.equal(missing.status, 404); |
| 29 | assert.equal(missing.headers.get("cache-control"), "no-store"); |
| 30 | const down = await serveArchivedAsset(new Request(url), undefined); |
| 31 | assert.equal(down.status, 503); |
| 32 | assert.equal(down.headers.get("cache-control"), "no-store"); |
| 33 | }); |