Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 68a13a4

Browse files
authored
fix: Ensure cookies set in middleware are available on initial render (#851)
* fix cookie set in middleware on initial render * e2e * add another test for internal next headers * refactor
1 parent 7a5c018 commit 68a13a4

File tree

6 files changed

+61
-9
lines changed

6 files changed

+61
-9
lines changed

.changeset/breezy-adults-behave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/aws": patch
3+
---
4+
5+
fix: Ensure cookies set in middleware are available on initial render when using `cookies().get()` from Next.js
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { cookies } from "next/headers";
2+
3+
export default async function Page() {
4+
const foo = (await cookies()).get("foo")?.value;
5+
6+
return <div data-testid="foo">{foo}</div>;
7+
}

examples/app-router/middleware.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ export function middleware(request: NextRequest) {
2828
const u = new URL("https://opennext.js.org/share.png");
2929
return NextResponse.rewrite(u);
3030
}
31+
if (path === "/cookies") {
32+
const res = NextResponse.next();
33+
res.cookies.set("foo", "bar");
34+
return res;
35+
}
3136
const requestHeaders = new Headers(request.headers);
3237
// Setting the Request Headers, this should be available in RSC
3338
requestHeaders.set("request-header", "request-header");

packages/open-next/src/core/requestHandler.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ export async function openNextHandler(
8787
continue;
8888
}
8989
const key = rawKey.slice(MIDDLEWARE_HEADER_PREFIX_LEN);
90-
overwrittenResponseHeaders[key] = value;
90+
// We skip this header here since it is used by Next internally and we don't want it on the response headers.
91+
// This header needs to be present in the request headers for processRequest, so cookies().get() from Next will work on initial render.
92+
if (key !== "x-middleware-set-cookie") {
93+
overwrittenResponseHeaders[key] = value;
94+
}
9195
headers[key] = value;
9296
delete headers[rawKey];
9397
}

packages/open-next/src/core/routing/middleware.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ export async function handleMiddleware(
115115
// These are internal headers used by Next.js, we don't want to expose them to the client
116116
const filteredHeaders = [
117117
"x-middleware-override-headers",
118-
"x-middleware-set-cookie",
119118
"x-middleware-next",
120119
"x-middleware-rewrite",
121120
// We need to drop `content-encoding` because it will be decoded
Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,44 @@
11
import { expect, test } from "@playwright/test";
22

3-
test("Cookies", async ({ page, context }) => {
4-
await page.goto("/");
3+
test.describe("Middleware Cookies", () => {
4+
test("should be able to set cookies on response in middleware", async ({
5+
page,
6+
context,
7+
}) => {
8+
await page.goto("/");
59

6-
const cookies = await context.cookies();
7-
const from = cookies.find(({ name }) => name === "from");
8-
expect(from?.value).toEqual("middleware");
10+
const cookies = await context.cookies();
11+
const from = cookies.find(({ name }) => name === "from");
12+
expect(from?.value).toEqual("middleware");
913

10-
const love = cookies.find(({ name }) => name === "with");
11-
expect(love?.value).toEqual("love");
14+
const love = cookies.find(({ name }) => name === "with");
15+
expect(love?.value).toEqual("love");
16+
});
17+
test("should be able to get cookies set in the middleware with Next's cookies().get()", async ({
18+
page,
19+
}) => {
20+
await page.goto("/cookies");
21+
22+
expect(await page.getByTestId("foo").textContent()).toBe("bar");
23+
});
24+
test("should not expose internal Next headers in response", async ({
25+
page,
26+
context,
27+
}) => {
28+
const responsePromise = page.waitForResponse((response) =>
29+
response.url().includes("/cookies"),
30+
);
31+
32+
await page.goto("/cookies");
33+
34+
const response = await responsePromise;
35+
const headers = response.headers();
36+
37+
const cookies = await context.cookies();
38+
const fooCookie = cookies.find(({ name }) => name === "foo");
39+
expect(fooCookie?.value).toBe("bar");
40+
41+
expect(headers).not.toHaveProperty("x-middleware-set-cookie");
42+
expect(headers).not.toHaveProperty("x-middleware-next");
43+
});
1244
});

0 commit comments

Comments
 (0)