From 9aee1ea96707a8a60c30619326357a631384288a Mon Sep 17 00:00:00 2001 From: daniluk4000 Date: Sat, 2 Nov 2024 16:27:40 +0300 Subject: [PATCH 1/6] feat: allow custom Vary header --- src/runtime/internal/static.ts | 6 +++++- test/fixture/plugins/vary.ts | 6 ++++++ test/fixture/public/foo.css | 0 test/fixture/public/foo.js | 0 test/presets/cloudflare-pages.test.ts | 2 ++ test/tests.ts | 16 ++++++++++++++++ 6 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 test/fixture/plugins/vary.ts create mode 100644 test/fixture/public/foo.css create mode 100644 test/fixture/public/foo.js diff --git a/src/runtime/internal/static.ts b/src/runtime/internal/static.ts index 81db44b068..39cfcdff40 100644 --- a/src/runtime/internal/static.ts +++ b/src/runtime/internal/static.ts @@ -49,7 +49,11 @@ export default eventHandler((event) => { "", ]; if (encodings.length > 1) { - setResponseHeader(event, "Vary", "Accept-Encoding"); + const varyHeader = getResponseHeader(event, 'Vary'); + + if(!varyHeader) setResponseHeader(event, "Vary", "Accept-Encoding"); + else if (typeof varyHeader === "string" && !varyHeader.includes('Accept-Encoding')) setResponseHeader(event, "Vary", `${ varyHeader }, Accept-Encoding`); + else if (Array.isArray(varyHeader) && !varyHeader.includes('Accept-Encoding')) setResponseHeader(event, "Vary", [...varyHeader, 'Accept-Encoding']); } for (const encoding of encodings) { diff --git a/test/fixture/plugins/vary.ts b/test/fixture/plugins/vary.ts new file mode 100644 index 0000000000..be368cb8c5 --- /dev/null +++ b/test/fixture/plugins/vary.ts @@ -0,0 +1,6 @@ +export default defineNitroPlugin((app) => { + app.hooks.hook("request", (event) => { + if(event.path.endsWith('.css')) setResponseHeader(event, 'Vary', 'Origin'); + if(event.path.endsWith('.js')) setResponseHeader(event, 'Vary', ['Origin']); + }); +}); diff --git a/test/fixture/public/foo.css b/test/fixture/public/foo.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixture/public/foo.js b/test/fixture/public/foo.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/presets/cloudflare-pages.test.ts b/test/presets/cloudflare-pages.test.ts index f6bbf25f9b..4b5a3d5af6 100644 --- a/test/presets/cloudflare-pages.test.ts +++ b/test/presets/cloudflare-pages.test.ts @@ -48,6 +48,8 @@ describe.skipIf(isWindows)("nitro:preset:cloudflare-pages", async () => { "/_swagger", "/_unignored.txt", "/favicon.ico", + "/foo.css", + "/foo.js", "/json-string", "/prerender", "/prerender-custom", diff --git a/test/tests.ts b/test/tests.ts index 0b5011a367..94659399e1 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -310,6 +310,22 @@ export function testNitro( expect(data).toMatch("

Hello JSX!

"); }); + it.skipIf(ctx.preset.startsWith('cloudflare') || ctx.preset === 'vercel-edge')( + "handles custom Vary header", + async () => { + let headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "gzip" } })).headers; + if (headers["vary"]) expect(headers["vary"]).toBe("Origin, Accept-Encoding"); + + headers = (await callHandler({ url: "/foo.js", headers: { "Accept-Encoding": "gzip" } })).headers; + + //For some reason, sometimes there are no space between Origin and Accept-Encoding when passing headers as an array + if (headers["vary"]) { + expect(headers["vary"].includes('Origin')).toBeTruthy(); + expect(headers["vary"].includes('Accept-Encoding')).toBeTruthy(); + } + } + ); + it("handles route rules - headers", async () => { const { headers } = await callHandler({ url: "/rules/headers" }); expect(headers["cache-control"]).toBe("s-maxage=60"); From 0f9f01865ad0bb42010ab08382d14fc8dd601b4b Mon Sep 17 00:00:00 2001 From: daniluk4000 Date: Sat, 2 Nov 2024 16:31:33 +0300 Subject: [PATCH 2/6] test: update test to check empty Accept-Encoding header --- test/tests.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/tests.ts b/test/tests.ts index 94659399e1..3eb434089c 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -316,6 +316,9 @@ export function testNitro( let headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "gzip" } })).headers; if (headers["vary"]) expect(headers["vary"]).toBe("Origin, Accept-Encoding"); + headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } })).headers; + if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); + headers = (await callHandler({ url: "/foo.js", headers: { "Accept-Encoding": "gzip" } })).headers; //For some reason, sometimes there are no space between Origin and Accept-Encoding when passing headers as an array From 0e49e1a7b313e83e5220848bf520f5649fe208cc Mon Sep 17 00:00:00 2001 From: daniluk4000 Date: Mon, 4 Nov 2024 15:29:59 +0300 Subject: [PATCH 3/6] refactor: use appendResponseHeader, fix lint --- src/runtime/internal/static.ts | 7 ++--- test/fixture/public/foo.js | 1 + test/tests.ts | 50 ++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/runtime/internal/static.ts b/src/runtime/internal/static.ts index 39cfcdff40..95c0599230 100644 --- a/src/runtime/internal/static.ts +++ b/src/runtime/internal/static.ts @@ -6,6 +6,7 @@ import { getResponseHeader, removeResponseHeader, setResponseHeader, + appendResponseHeader, setResponseStatus, } from "h3"; import type { PublicAsset } from "nitropack/types"; @@ -49,11 +50,7 @@ export default eventHandler((event) => { "", ]; if (encodings.length > 1) { - const varyHeader = getResponseHeader(event, 'Vary'); - - if(!varyHeader) setResponseHeader(event, "Vary", "Accept-Encoding"); - else if (typeof varyHeader === "string" && !varyHeader.includes('Accept-Encoding')) setResponseHeader(event, "Vary", `${ varyHeader }, Accept-Encoding`); - else if (Array.isArray(varyHeader) && !varyHeader.includes('Accept-Encoding')) setResponseHeader(event, "Vary", [...varyHeader, 'Accept-Encoding']); + appendResponseHeader(event, "Vary", "Accept-Encoding"); } for (const encoding of encodings) { diff --git a/test/fixture/public/foo.js b/test/fixture/public/foo.js index e69de29bb2..a9917c6ec3 100644 --- a/test/fixture/public/foo.js +++ b/test/fixture/public/foo.js @@ -0,0 +1 @@ +const hello = "world"; diff --git a/test/tests.ts b/test/tests.ts index 3eb434089c..8a08bdfc92 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -310,24 +310,38 @@ export function testNitro( expect(data).toMatch("

Hello JSX!

"); }); - it.skipIf(ctx.preset.startsWith('cloudflare') || ctx.preset === 'vercel-edge')( - "handles custom Vary header", - async () => { - let headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "gzip" } })).headers; - if (headers["vary"]) expect(headers["vary"]).toBe("Origin, Accept-Encoding"); - - headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } })).headers; - if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); - - headers = (await callHandler({ url: "/foo.js", headers: { "Accept-Encoding": "gzip" } })).headers; - - //For some reason, sometimes there are no space between Origin and Accept-Encoding when passing headers as an array - if (headers["vary"]) { - expect(headers["vary"].includes('Origin')).toBeTruthy(); - expect(headers["vary"].includes('Accept-Encoding')).toBeTruthy(); - } - } - ); + it.skipIf( + ctx.preset.startsWith("cloudflare") || ctx.preset === "vercel-edge" + )("handles custom Vary header", async () => { + let headers = ( + await callHandler({ + url: "/foo.css", + headers: { "Accept-Encoding": "gzip" }, + }) + ).headers; + if (headers["vary"]) + expect( + headers["vary"].includes("Origin") && + headers["vary"].includes("Accept-Encoding") + ).toBeTruthy(); + + headers = ( + await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } }) + ).headers; + if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); + + headers = ( + await callHandler({ + url: "/foo.js", + headers: { "Accept-Encoding": "gzip" }, + }) + ).headers; + if (headers["vary"]) + expect( + headers["vary"].includes("Origin") && + headers["vary"].includes("Accept-Encoding") + ).toBeTruthy(); + }); it("handles route rules - headers", async () => { const { headers } = await callHandler({ url: "/rules/headers" }); From 748ef172f6378a9a056d5416ee7f389ce06b3fc5 Mon Sep 17 00:00:00 2001 From: daniluk4000 Date: Mon, 4 Nov 2024 15:31:23 +0300 Subject: [PATCH 4/6] chore: fix test fomratting --- test/tests.ts | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/test/tests.ts b/test/tests.ts index 8a08bdfc92..ba84a26d26 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -310,38 +310,19 @@ export function testNitro( expect(data).toMatch("

Hello JSX!

"); }); - it.skipIf( - ctx.preset.startsWith("cloudflare") || ctx.preset === "vercel-edge" - )("handles custom Vary header", async () => { - let headers = ( - await callHandler({ - url: "/foo.css", - headers: { "Accept-Encoding": "gzip" }, - }) - ).headers; - if (headers["vary"]) - expect( - headers["vary"].includes("Origin") && - headers["vary"].includes("Accept-Encoding") - ).toBeTruthy(); - - headers = ( - await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } }) - ).headers; - if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); - - headers = ( - await callHandler({ - url: "/foo.js", - headers: { "Accept-Encoding": "gzip" }, - }) - ).headers; - if (headers["vary"]) - expect( - headers["vary"].includes("Origin") && - headers["vary"].includes("Accept-Encoding") - ).toBeTruthy(); - }); + it.skipIf(ctx.preset.startsWith('cloudflare') || ctx.preset === 'vercel-edge')( + "handles custom Vary header", + async () => { + let headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "gzip" } })).headers; + if (headers["vary"]) expect(headers["vary"].includes('Origin') && headers["vary"].includes('Accept-Encoding')).toBeTruthy(); + + headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } })).headers; + if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); + + headers = (await callHandler({ url: "/foo.js", headers: { "Accept-Encoding": "gzip" } })).headers; + if (headers["vary"]) expect(headers["vary"].includes('Origin') && headers["vary"].includes('Accept-Encoding')).toBeTruthy(); + } + ); it("handles route rules - headers", async () => { const { headers } = await callHandler({ url: "/rules/headers" }); From e57286d501cbfc3848fa5ffe27889d26b5e67175 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 5 Nov 2024 09:32:46 +0100 Subject: [PATCH 5/6] lint --- test/fixture/plugins/vary.ts | 5 ++-- test/tests.ts | 45 +++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/test/fixture/plugins/vary.ts b/test/fixture/plugins/vary.ts index be368cb8c5..f35543969e 100644 --- a/test/fixture/plugins/vary.ts +++ b/test/fixture/plugins/vary.ts @@ -1,6 +1,7 @@ export default defineNitroPlugin((app) => { app.hooks.hook("request", (event) => { - if(event.path.endsWith('.css')) setResponseHeader(event, 'Vary', 'Origin'); - if(event.path.endsWith('.js')) setResponseHeader(event, 'Vary', ['Origin']); + if (event.path.endsWith(".css")) setResponseHeader(event, "Vary", "Origin"); + if (event.path.endsWith(".js")) + setResponseHeader(event, "Vary", ["Origin"]); }); }); diff --git a/test/tests.ts b/test/tests.ts index 06f5366df6..83ba1c0af1 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -311,19 +311,38 @@ export function testNitro( expect(data).toMatch("

Hello JSX!

"); }); - it.skipIf(ctx.preset.startsWith('cloudflare') || ctx.preset === 'vercel-edge')( - "handles custom Vary header", - async () => { - let headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "gzip" } })).headers; - if (headers["vary"]) expect(headers["vary"].includes('Origin') && headers["vary"].includes('Accept-Encoding')).toBeTruthy(); - - headers = (await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } })).headers; - if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); - - headers = (await callHandler({ url: "/foo.js", headers: { "Accept-Encoding": "gzip" } })).headers; - if (headers["vary"]) expect(headers["vary"].includes('Origin') && headers["vary"].includes('Accept-Encoding')).toBeTruthy(); - } - ); + it.skipIf( + ctx.preset.startsWith("cloudflare") || ctx.preset === "vercel-edge" + )("handles custom Vary header", async () => { + let headers = ( + await callHandler({ + url: "/foo.css", + headers: { "Accept-Encoding": "gzip" }, + }) + ).headers; + if (headers["vary"]) + expect( + headers["vary"].includes("Origin") && + headers["vary"].includes("Accept-Encoding") + ).toBeTruthy(); + + headers = ( + await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } }) + ).headers; + if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); + + headers = ( + await callHandler({ + url: "/foo.js", + headers: { "Accept-Encoding": "gzip" }, + }) + ).headers; + if (headers["vary"]) + expect( + headers["vary"].includes("Origin") && + headers["vary"].includes("Accept-Encoding") + ).toBeTruthy(); + }); it("handles route rules - headers", async () => { const { headers } = await callHandler({ url: "/rules/headers" }); From ac183438f5a18c22f26b6603d359b04de52e5a50 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 5 Nov 2024 09:37:18 +0100 Subject: [PATCH 6/6] update test --- test/fixture/plugins/vary.ts | 7 ++-- test/tests.ts | 68 +++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/test/fixture/plugins/vary.ts b/test/fixture/plugins/vary.ts index f35543969e..d1dcd40d17 100644 --- a/test/fixture/plugins/vary.ts +++ b/test/fixture/plugins/vary.ts @@ -1,7 +1,10 @@ export default defineNitroPlugin((app) => { app.hooks.hook("request", (event) => { - if (event.path.endsWith(".css")) setResponseHeader(event, "Vary", "Origin"); - if (event.path.endsWith(".js")) + if (event.path.endsWith(".css")) { + setResponseHeader(event, "Vary", "Origin"); + } + if (event.path.endsWith(".js")) { setResponseHeader(event, "Vary", ["Origin"]); + } }); }); diff --git a/test/tests.ts b/test/tests.ts index 83ba1c0af1..5dbba0961f 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -311,38 +311,42 @@ export function testNitro( expect(data).toMatch("

Hello JSX!

"); }); - it.skipIf( - ctx.preset.startsWith("cloudflare") || ctx.preset === "vercel-edge" - )("handles custom Vary header", async () => { - let headers = ( - await callHandler({ - url: "/foo.css", - headers: { "Accept-Encoding": "gzip" }, - }) - ).headers; - if (headers["vary"]) - expect( - headers["vary"].includes("Origin") && - headers["vary"].includes("Accept-Encoding") - ).toBeTruthy(); - - headers = ( - await callHandler({ url: "/foo.css", headers: { "Accept-Encoding": "" } }) - ).headers; - if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); - - headers = ( - await callHandler({ - url: "/foo.js", - headers: { "Accept-Encoding": "gzip" }, - }) - ).headers; - if (headers["vary"]) - expect( - headers["vary"].includes("Origin") && - headers["vary"].includes("Accept-Encoding") - ).toBeTruthy(); - }); + it.runIf(ctx.nitro?.options.serveStatic)( + "handles custom Vary header", + async () => { + let headers = ( + await callHandler({ + url: "/foo.css", + headers: { "Accept-Encoding": "gzip" }, + }) + ).headers; + if (headers["vary"]) + expect( + headers["vary"].includes("Origin") && + headers["vary"].includes("Accept-Encoding") + ).toBeTruthy(); + + headers = ( + await callHandler({ + url: "/foo.css", + headers: { "Accept-Encoding": "" }, + }) + ).headers; + if (headers["vary"]) expect(headers["vary"]).toBe("Origin"); + + headers = ( + await callHandler({ + url: "/foo.js", + headers: { "Accept-Encoding": "gzip" }, + }) + ).headers; + if (headers["vary"]) + expect( + headers["vary"].includes("Origin") && + headers["vary"].includes("Accept-Encoding") + ).toBeTruthy(); + } + ); it("handles route rules - headers", async () => { const { headers } = await callHandler({ url: "/rules/headers" });