Skip to content

Commit 93c8766

Browse files
committed
test: validate functionality of mergeMiddlewareCookies
1 parent c8379d6 commit 93c8766

File tree

3 files changed

+111
-9
lines changed

3 files changed

+111
-9
lines changed

edge-runtime/lib/middleware.test.ts

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts'
2+
import { mergeMiddlewareCookies } from './middleware.ts'
3+
4+
const MIDDLEWARE_HEADER = 'x-middleware-set-cookie'
5+
6+
Deno.test('mergeMiddlewareCookies', async (t) => {
7+
await t.step('should handle empty cookies', async () => {
8+
const request = new Request('https://www.test-url.com')
9+
const response = new Response()
10+
11+
const result = mergeMiddlewareCookies(response, request)
12+
assertEquals(result, '')
13+
})
14+
15+
await t.step('should return request cookies when there are no middleware headers', async () => {
16+
const request = new Request('https://www.test-url.com')
17+
const response = new Response()
18+
19+
request.headers.set('Cookie', 'oatmeal=raisin')
20+
21+
const result = mergeMiddlewareCookies(response, request)
22+
assertEquals(result, 'oatmeal=raisin')
23+
})
24+
25+
await t.step('should not require cookies in request to be set', async () => {
26+
const request = new Request('https://www.test-url.com')
27+
const response = new Response()
28+
29+
response.headers.set(MIDDLEWARE_HEADER, 'peanut=butter; Path=/')
30+
31+
const result = mergeMiddlewareCookies(response, request)
32+
assertEquals(result, 'peanut=butter')
33+
})
34+
35+
await t.step('should merge request and middleware cookies', async () => {
36+
const request = new Request('https://www.test-url.com')
37+
const response = new Response()
38+
39+
request.headers.set('Cookie', 'oatmeal=raisin')
40+
response.headers.set(MIDDLEWARE_HEADER, 'peanut=butter; Path=/')
41+
42+
const result = mergeMiddlewareCookies(response, request)
43+
assertEquals(result, 'oatmeal=raisin; peanut=butter')
44+
})
45+
46+
await t.step('should overwrite request cookies with latest values', async () => {
47+
const request = new Request('https://www.test-url.com')
48+
const response = new Response()
49+
50+
request.headers.set('Cookie', 'oatmeal=chocolate')
51+
response.headers.set(MIDDLEWARE_HEADER, 'oatmeal=raisin; Path=/')
52+
53+
const result = mergeMiddlewareCookies(response, request)
54+
assertEquals(result, 'oatmeal=raisin')
55+
})
56+
57+
await t.step('should not decode middleware cookie values', async () => {
58+
const request = new Request('https://www.test-url.com')
59+
const response = new Response()
60+
61+
response.headers.set(
62+
MIDDLEWARE_HEADER,
63+
'greeting=Hello%20from%20the%20cookie; Path=/',
64+
)
65+
66+
const result = mergeMiddlewareCookies(response, request)
67+
assertEquals(result, 'greeting=Hello%20from%20the%20cookie')
68+
})
69+
70+
await t.step('should support multiple cookies being set in middleware', async () => {
71+
const request = new Request('https://www.test-url.com')
72+
const response = new Response()
73+
74+
response.headers.set(
75+
MIDDLEWARE_HEADER,
76+
'oatmeal=raisin; Path=/,peanut=butter; Path=/,chocolate=chip; Path=/',
77+
)
78+
79+
const result = mergeMiddlewareCookies(response, request)
80+
assertEquals(result, 'oatmeal=raisin; peanut=butter; chocolate=chip')
81+
})
82+
83+
await t.step('should ignore comma in middleware cookie expiry', async () => {
84+
const request = new Request('https://www.test-url.com')
85+
const response = new Response()
86+
87+
response.headers.set(
88+
MIDDLEWARE_HEADER,
89+
'oatmeal=raisin; Path=/; Expires=Wed, 23 Apr 2025 13:37:43 GMT; Max-Age=604800',
90+
)
91+
92+
const result = mergeMiddlewareCookies(response, request)
93+
assertEquals(result, 'oatmeal=raisin')
94+
})
95+
})

edge-runtime/lib/middleware.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,20 @@ export const addMiddlewareHeaders = async (
6060
return response
6161
}
6262

63-
export function mergeMiddlewareCookies(middlewareResponse: Response, request: Request) {
64-
let mergedCookies = getCookies(request.headers)
65-
const middlewareCookies = middlewareResponse.headers.get('x-middleware-set-cookie') || ''
63+
// This serves the same purpose as the mergeMiddlewareCookies in Next.js but has been customized to our domain
64+
// See: https://github.com/vercel/next.js/blob/6e4495f8430eab33b12cd11dffdd8e27eee6e0cf/packages/next/src/server/async-storage/request-store.ts#L78-L105
65+
export function mergeMiddlewareCookies(middlewareResponse: Response, lambdaRequest: Request) {
66+
let mergedCookies = getCookies(lambdaRequest.headers)
67+
const middlewareCookies = middlewareResponse.headers.get('x-middleware-set-cookie')
6668
const regex = new RegExp(/,(?!\s)/) // commas that are not followed by whitespace
6769

68-
middlewareCookies.split(regex).forEach((entry) => {
69-
const [cookie] = entry.split(';')
70-
const [name, value] = cookie.split('=')
71-
mergedCookies[name] = value
72-
})
70+
if (middlewareCookies) {
71+
middlewareCookies.split(regex).forEach((entry) => {
72+
const [cookie] = entry.split(';')
73+
const [name, value] = cookie.split('=')
74+
mergedCookies[name] = value
75+
})
76+
}
7377

7478
return Object.entries(mergedCookies)
7579
.map((kv) => kv.join('='))

edge-runtime/lib/response.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,10 @@ export const buildResponse = async ({
234234

235235
// coookies set in middleware need to be available during the lambda request
236236
const newRequest = new Request(request)
237-
newRequest.headers.set('Cookie', mergeMiddlewareCookies(edgeResponse, newRequest))
237+
const newRequestCookies = mergeMiddlewareCookies(edgeResponse, newRequest)
238+
if (newRequestCookies) {
239+
newRequest.headers.set('Cookie', newRequestCookies)
240+
}
238241

239242
return addMiddlewareHeaders(context.next(newRequest), edgeResponse)
240243
}

0 commit comments

Comments
 (0)