Skip to content

Commit

Permalink
fix middleware cookie initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed May 15, 2024
1 parent fdd8f0c commit 74f276a
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import {
RequestCookiesAdapter,
type ReadonlyRequestCookies,
} from '../web/spec-extension/adapters/request-cookies'
import type { ResponseCookies } from '../web/spec-extension/cookies'
import { RequestCookies } from '../web/spec-extension/cookies'
import { ResponseCookies, RequestCookies } from '../web/spec-extension/cookies'
import { DraftModeProvider } from './draft-mode-provider'
import { splitCookiesString } from '../web/utils'

function getHeaders(headers: Headers | IncomingHttpHeaders): ReadonlyHeaders {
const cleaned = HeadersAdapter.from(headers)
Expand Down Expand Up @@ -108,7 +108,27 @@ export const RequestAsyncStorageWrapper: AsyncStorageWrapper<
'x-middleware-set-cookie' in req.headers &&
typeof req.headers['x-middleware-set-cookie'] === 'string'
) {
combinedCookies = `${req.headers.cookie}; ${req.headers['x-middleware-set-cookie']}`
const setCookieValue = req.headers['x-middleware-set-cookie']
const responseHeaders = new Headers()

for (const cookie of splitCookiesString(setCookieValue)) {
responseHeaders.append('set-cookie', cookie)
}

const responseCookies = new ResponseCookies(responseHeaders)
const requestCookies = new RequestCookies(new Headers())

// Transfer cookies from ResponseCookies to RequestCookies
for (const cookie of responseCookies.getAll()) {
requestCookies.set(cookie.name, cookie.value ?? '')
}

combinedCookies = requestCookies.toString()

// Only merge existing cookies if they exist
if (req.headers.cookie) {
combinedCookies = `${req.headers.cookie}; ${combinedCookies}`
}
}

// Seal the cookies object that'll freeze out any methods that could
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/server/web/spec-extension/cookies.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {
RequestCookies,
ResponseCookies,
stringifyCookie,
} from 'next/dist/compiled/@edge-runtime/cookies'
9 changes: 8 additions & 1 deletion packages/next/src/server/web/spec-extension/response.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { stringifyCookie } from '../../web/spec-extension/cookies'
import type { I18NConfig } from '../../config-shared'
import { NextURL } from '../next-url'
import { toNodeOutgoingHttpHeaders, validateURL } from '../utils'
Expand Down Expand Up @@ -55,7 +56,13 @@ export class NextResponse<Body = unknown> extends Response {
const newHeaders = new Headers(headers)

if (result instanceof ResponseCookies) {
headers.set('x-middleware-set-cookie', result.toString())
headers.set(
'x-middleware-set-cookie',
result
.getAll()
.map((cookie) => stringifyCookie(cookie))
.join(',')
)
}

handleMiddlewareField(init, newHeaders)
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/app-dir/app-middleware/app-middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,12 @@ describe('app-dir with middleware', () => {

const initialRandom1 = await browser.elementById('rsc-cookie-1').text()
const initialRandom2 = await browser.elementById('rsc-cookie-2').text()
const totalCookies = await browser.elementById('total-cookies').text()

// cookies were set in middleware, assert they are present and match the Math.random() pattern
expect(initialRandom1).toMatch(/Cookie 1: \d+\.\d+/)
expect(initialRandom2).toMatch(/Cookie 2: \d+\.\d+/)
expect(totalCookies).toBe('Total Cookie Length: 2')

await browser.refresh()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default function Page() {
<div>
<p id="rsc-cookie-1">Cookie 1: {rscCookie1}</p>
<p id="rsc-cookie-2">Cookie 2: {rscCookie2}</p>
<p id="total-cookies">Total Cookie Length: {cookies().size}</p>
</div>
)
}
1 change: 1 addition & 0 deletions test/e2e/app-dir/app-middleware/app/rsc-cookies/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function Page() {
<div>
<p id="rsc-cookie-1">Cookie 1: {rscCookie1}</p>
<p id="rsc-cookie-2">Cookie 2: {rscCookie2}</p>
<p id="total-cookies">Total Cookie Length: {cookies().size}</p>
<Link href="/rsc-cookies-delete">To Delete Cookies Route</Link>
</div>
)
Expand Down

0 comments on commit 74f276a

Please sign in to comment.