Skip to content

Commit 6f92e7d

Browse files
authored
Fix/cookie matcher (#268)
* fix cookie redirect matcher
1 parent 2575f04 commit 6f92e7d

File tree

5 files changed

+121
-4
lines changed

5 files changed

+121
-4
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default function RedirectDestination() {
2+
return (
3+
<div>
4+
<h1>I was redirected from next.config.js</h1>
5+
<p>/next-config-redirect =&gt; /config-redirect</p>
6+
</div>
7+
);
8+
}

examples/app-router/next.config.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,40 @@ const nextConfig = {
88
experimental: {
99
serverActions: true,
1010
},
11+
redirects: () => {
12+
return [
13+
{
14+
source: "/next-config-redirect-missing",
15+
destination: "/config-redirect?missing=true",
16+
permanent: true,
17+
missing: [{ type: "cookie", key: "missing-cookie" }],
18+
},
19+
{
20+
source: "/next-config-redirect-not-missing",
21+
destination: "/config-redirect?missing=true",
22+
permanent: true,
23+
missing: [{ type: "cookie", key: "from" }], // middleware sets this cookie
24+
},
25+
{
26+
source: "/next-config-redirect-has",
27+
destination: "/config-redirect?has=true",
28+
permanent: true,
29+
has: [{ type: "cookie", key: "from" }],
30+
},
31+
{
32+
source: "/next-config-redirect-has-with-value",
33+
destination: "/config-redirect?hasWithValue=true",
34+
permanent: true,
35+
has: [{ type: "cookie", key: "from", value: "middleware" }],
36+
},
37+
{
38+
source: "/next-config-redirect-has-with-bad-value",
39+
destination: "/config-redirect?hasWithBadValue=true",
40+
permanent: true,
41+
has: [{ type: "cookie", key: "from", value: "wrongvalue" }],
42+
},
43+
];
44+
},
1145
headers() {
1246
return [
1347
{

packages/open-next/src/adapters/routing/matcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ const routeHasMatcher =
2222
switch (redirect.type) {
2323
case "header":
2424
return (
25-
headers?.[redirect.key.toLowerCase()] !== "" &&
25+
!!headers?.[redirect.key.toLowerCase()] &&
2626
new RegExp(redirect.value ?? "").test(
2727
headers[redirect.key.toLowerCase()] ?? "",
2828
)
2929
);
3030
case "cookie":
3131
return (
32-
cookies?.[redirect.key] !== "" &&
32+
!!cookies?.[redirect.key] &&
3333
new RegExp(redirect.value ?? "").test(cookies[redirect.key] ?? "")
3434
);
3535
case "query":

packages/open-next/src/adapters/routing/util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ export function getUrlParts(url: string, isExternal: boolean) {
1515
if (!isExternal) {
1616
return {
1717
hostname: "",
18-
pathname: url,
18+
pathname: encodeURIComponent(url),
1919
protocol: "",
2020
};
2121
}
2222
const { hostname, pathname, protocol } = new URL(url);
2323
return {
2424
hostname,
25-
pathname,
25+
pathname: encodeURIComponent(pathname),
2626
protocol,
2727
};
2828
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { expect, test } from "@playwright/test";
2+
/**
3+
* This tests that the "redirect" config in next.config.js works
4+
*
5+
* redirects: () => {
6+
return [
7+
{
8+
source: "/next-config-redirect",
9+
destination: "/config-redirect",
10+
permanent: true,
11+
missing: [{ type: "cookie", key: "missing-cookie" }],
12+
},
13+
];
14+
},
15+
*/
16+
test.describe("Next Config Redirect", () => {
17+
test("Missing cookies", async ({ page }) => {
18+
await page.goto("/");
19+
await page.goto("/next-config-redirect-missing");
20+
21+
await page.waitForURL(`/config-redirect?missing=true`);
22+
23+
const el = page.getByText("I was redirected from next.config.js", {
24+
exact: true,
25+
});
26+
await expect(el).toBeVisible();
27+
});
28+
test("Not missing cookies", async ({ page }) => {
29+
await page.goto("/");
30+
await page.goto("/next-config-redirect-not-missing");
31+
32+
// the cookie was not missing, so no redirects
33+
await page.waitForURL("/next-config-redirect-not-missing");
34+
35+
const el = page.getByText("This page could not be found.", {
36+
exact: true,
37+
});
38+
await expect(el).toBeVisible();
39+
});
40+
test("Has cookies", async ({ page }) => {
41+
await page.goto("/");
42+
await page.goto("/next-config-redirect-has");
43+
44+
await page.waitForURL(`/config-redirect?has=true`);
45+
46+
const el = page.getByText("I was redirected from next.config.js", {
47+
exact: true,
48+
});
49+
await expect(el).toBeVisible();
50+
});
51+
test("Has cookies with value", async ({ page }) => {
52+
await page.goto("/");
53+
await page.goto("/next-config-redirect-has-with-value");
54+
55+
await page.waitForURL(`/config-redirect?hasWithValue=true`);
56+
57+
const el = page.getByText("I was redirected from next.config.js", {
58+
exact: true,
59+
});
60+
await expect(el).toBeVisible();
61+
});
62+
test("Has cookies with bad value", async ({ page }) => {
63+
await page.goto("/");
64+
await page.goto("/next-config-redirect-has-with-bad-value");
65+
66+
// did not redirect
67+
await page.waitForURL(`/next-config-redirect-has-with-bad-value`);
68+
69+
// 404 not found
70+
const el = page.getByText("This page could not be found.", {
71+
exact: true,
72+
});
73+
await expect(el).toBeVisible();
74+
});
75+
});

0 commit comments

Comments
 (0)