From c502308bca73a0cbc615ee56cd08eeae317fd4ce Mon Sep 17 00:00:00 2001 From: Nikhil Mehta <6815560+technikhil314@users.noreply.github.com> Date: Fri, 5 Apr 2024 02:38:13 +0530 Subject: [PATCH] fix: cookie override during redirection from server action (#61633) ### What? Fixes #61611 ### Why? Any one having custom server may be having logic to set cookies during GET requests too. Currently nextjs in app directory does not allow to do so but with custom server its very much possible. ### How? By merging cookies of redirect response and server action POSt response ### Tests I have added one more test to existing suite and it passing with fix in place. ![image](https://github.com/vercel/next.js/assets/6815560/858afdbb-c377-49eb-9002-fcbdf06583a4) ### Notes This bug is reproducible only if developer has custom server on top of next app but still very probable --------- Co-authored-by: Shu Ding Co-authored-by: JJ Kasper --- .../next/src/server/lib/server-ipc/utils.ts | 1 + .../custom-server/app/page.js | 6 ++++- .../custom-server/server.js | 5 +++- .../app-basepath-custom-server/index.test.ts | 25 +++++++++++++++++-- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/packages/next/src/server/lib/server-ipc/utils.ts b/packages/next/src/server/lib/server-ipc/utils.ts index 06a981d166bd0..3c09bf476b8d7 100644 --- a/packages/next/src/server/lib/server-ipc/utils.ts +++ b/packages/next/src/server/lib/server-ipc/utils.ts @@ -13,6 +13,7 @@ export const ipcForbiddenHeaders = [ export const actionsForbiddenHeaders = [ ...ipcForbiddenHeaders, 'content-length', + 'set-cookie', ] export const filterReqHeaders = ( diff --git a/test/e2e/app-dir/app-basepath-custom-server/custom-server/app/page.js b/test/e2e/app-dir/app-basepath-custom-server/custom-server/app/page.js index 9e075292ee056..b150de920f39a 100644 --- a/test/e2e/app-dir/app-basepath-custom-server/custom-server/app/page.js +++ b/test/e2e/app-dir/app-basepath-custom-server/custom-server/app/page.js @@ -1,8 +1,12 @@ import { redirect } from 'next/navigation' +import { cookies } from 'next/headers' async function action() { 'use server' - + cookies().set( + 'custom-server-action-test-cookie', + 'custom-server-action-test-cookie-val' + ) redirect('/another') } diff --git a/test/e2e/app-dir/app-basepath-custom-server/custom-server/server.js b/test/e2e/app-dir/app-basepath-custom-server/custom-server/server.js index 566c980b9e430..ecbaf8077d849 100644 --- a/test/e2e/app-dir/app-basepath-custom-server/custom-server/server.js +++ b/test/e2e/app-dir/app-basepath-custom-server/custom-server/server.js @@ -18,7 +18,10 @@ async function main() { try { const parsedUrl = parse(req.url, true) const { pathname } = parsedUrl - + res.setHeader( + 'set-cookie', + 'custom-server-test-cookie=custom-server-test-cookie-val' + ) if (pathname.startsWith('/base')) { await handle(req, res, parsedUrl) } else { diff --git a/test/e2e/app-dir/app-basepath-custom-server/index.test.ts b/test/e2e/app-dir/app-basepath-custom-server/index.test.ts index 57a9f9abf988c..4f87c263217b5 100644 --- a/test/e2e/app-dir/app-basepath-custom-server/index.test.ts +++ b/test/e2e/app-dir/app-basepath-custom-server/index.test.ts @@ -1,6 +1,6 @@ -import { join } from 'path' import { createNextDescribe } from 'e2e-utils' -import { retry } from 'next-test-utils' +import { check, retry } from 'next-test-utils' +import { join } from 'path' createNextDescribe( 'custom-app-server-action-redirect', @@ -35,5 +35,26 @@ createNextDescribe( // Count should still be 2 as the browser should not have reloaded the page. expect(await getCount()).toBe('Count: 2') }) + + it('redirects with proper cookies set from both redirect response and post respose', async () => { + const browser = await next.browser('/base') + + await browser.elementById('submit-server-action-redirect').click() + + expect(await browser.waitForElementByCss('#another').text()).toBe( + 'Another Page' + ) + expect(await browser.url()).toBe( + `http://localhost:${next.appPort}/base/another` + ) + await check( + () => browser.eval('document.cookie'), + /custom-server-test-cookie/ + ) + await check( + () => browser.eval('document.cookie'), + /custom-server-action-test-cookie/ + ) + }) } )