From ed2499e432e695c2abc833743b90c1697a37c60d Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Thu, 22 Jun 2023 17:47:35 +0100 Subject: [PATCH 1/2] Add url to patched fetch response --- packages/next/src/server/lib/patch-fetch.ts | 11 ++++++-- .../next/src/server/response-cache/types.ts | 1 + .../web/spec-extension/unstable-cache.ts | 1 + .../e2e/app-dir/app-static/app-static.test.ts | 21 +++++++++++++++ .../app-static/app/response-url/page.js | 26 +++++++++++++++++++ 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 test/e2e/app-dir/app-static/app/response-url/page.js diff --git a/packages/next/src/server/lib/patch-fetch.ts b/packages/next/src/server/lib/patch-fetch.ts index 0ae313a0b6a69..bdbc6ac12075d 100644 --- a/packages/next/src/server/lib/patch-fetch.ts +++ b/packages/next/src/server/lib/patch-fetch.ts @@ -374,6 +374,7 @@ export function patchFetch({ body: bodyBuffer.toString('base64'), status: res.status, tags, + url: res.url, }, revalidate: normalizedRevalidate, }, @@ -386,10 +387,12 @@ export function patchFetch({ console.warn(`Failed to set fetch cache`, input, err) } - return new Response(bodyBuffer, { + const response = new Response(bodyBuffer, { headers: new Headers(res.headers), status: res.status, }) + Object.defineProperty(response, 'url', { value: res.url }) + return response } return res }) @@ -463,10 +466,14 @@ export function patchFetch({ method: init?.method || 'GET', }) - return new Response(decodedBody, { + const response = new Response(decodedBody, { headers: resData.headers, status: resData.status, }) + Object.defineProperty(response, 'url', { + value: entry.value.data.url, + }) + return response } } } diff --git a/packages/next/src/server/response-cache/types.ts b/packages/next/src/server/response-cache/types.ts index 938052b2d44d8..23814b11fb5c5 100644 --- a/packages/next/src/server/response-cache/types.ts +++ b/packages/next/src/server/response-cache/types.ts @@ -18,6 +18,7 @@ export interface CachedFetchValue { data: { headers: { [k: string]: string } body: string + url: string status?: number tags?: string[] } diff --git a/packages/next/src/server/web/spec-extension/unstable-cache.ts b/packages/next/src/server/web/spec-extension/unstable-cache.ts index 188aa5d71ff9d..e09e54de20b7e 100644 --- a/packages/next/src/server/web/spec-extension/unstable-cache.ts +++ b/packages/next/src/server/web/spec-extension/unstable-cache.ts @@ -86,6 +86,7 @@ export function unstable_cache( body: JSON.stringify(result), status: 200, tags, + url: '', }, revalidate: typeof options.revalidate !== 'number' diff --git a/test/e2e/app-dir/app-static/app-static.test.ts b/test/e2e/app-dir/app-static/app-static.test.ts index 1b8ec7f42c2cc..10ccc96ae843b 100644 --- a/test/e2e/app-dir/app-static/app-static.test.ts +++ b/test/e2e/app-dir/app-static/app-static.test.ts @@ -1125,6 +1125,27 @@ createNextDescribe( } }) + it('should produce response with url from fetch', async () => { + const res = await next.fetch('/response-url') + expect(res.status).toBe(200) + + const html = await res.text() + const $ = cheerio.load(html) + + expect($('#data-url-default-cache').text()).toBe( + 'https://next-data-api-endpoint.vercel.app/api/random?a1' + ) + expect($('#data-url-no-cache').text()).toBe( + 'https://next-data-api-endpoint.vercel.app/api/random?b2' + ) + expect($('#data-url-cached').text()).toBe( + 'https://next-data-api-endpoint.vercel.app/api/random?a1' + ) + expect($('#data-value-default-cache').text()).toBe( + $('#data-value-cached').text() + ) + }) + it('should properly error when dynamic = "error" page uses dynamic', async () => { const res = await next.fetch('/dynamic-error/static-bailout-1') const outputIndex = next.cliOutput.length diff --git a/test/e2e/app-dir/app-static/app/response-url/page.js b/test/e2e/app-dir/app-static/app/response-url/page.js new file mode 100644 index 0000000000000..c5c19ec35f1eb --- /dev/null +++ b/test/e2e/app-dir/app-static/app/response-url/page.js @@ -0,0 +1,26 @@ +export const fetchCache = 'default-cache' + +export default async function Page() { + const [urlDefaultCache, valueDefaultCache] = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/random?a1' + ).then((res) => Promise.all([res.url, res.text()])) + + const urlNoCache = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/random?b2', + { cache: 'no-store' } + ).then((res) => res.url) + + const [urlCached, valueCached] = await fetch( + 'https://next-data-api-endpoint.vercel.app/api/random?a1' + ).then((res) => Promise.all([res.url, res.text()])) + + return ( + <> +

{urlDefaultCache}

+

{valueDefaultCache}

+

{urlNoCache}

+

{urlCached}

+

{valueCached}

+ + ) +} From be0ed1595a98bd3c714b3a75d239babcbf2c83ef Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Fri, 23 Jun 2023 14:26:12 -0700 Subject: [PATCH 2/2] update test --- test/e2e/app-dir/app-static/app-static.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/app-dir/app-static/app-static.test.ts b/test/e2e/app-dir/app-static/app-static.test.ts index 6913f697245ac..208860eff248e 100644 --- a/test/e2e/app-dir/app-static/app-static.test.ts +++ b/test/e2e/app-dir/app-static/app-static.test.ts @@ -553,6 +553,7 @@ createNextDescribe( 'partial-gen-params/[lang]/[slug]/page.js', 'react-fetch-deduping-edge/page.js', 'react-fetch-deduping-node/page.js', + 'response-url/page.js', 'route-handler-edge/revalidate-360/route.js', 'route-handler/post/route.js', 'route-handler/revalidate-360-isr/route.js',