Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
export default async function RewriteDestination(props: { searchParams: Promise<{ a: string }> }) {
export default async function RewriteDestination(props: {
searchParams: Promise<{ a: string; multi?: string[] }>;
}) {
const searchParams = await props.searchParams;
return (
<div>
<div>Rewritten Destination</div>
<div>a: {searchParams.a}</div>
<div>multi: {searchParams.multi?.join(", ")}</div>
</div>
);
}
53 changes: 38 additions & 15 deletions examples/e2e/app-pages-router/e2e/middleware.rewrite.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
import { expect, test } from "@playwright/test";

test("Middleware Rewrite", async ({ page }) => {
await page.goto("/");
await page.locator('[href="/rewrite"]').click();
test.describe("Middleware Rewrite", () => {
test("Simple Middleware Rewrite", async ({ page }) => {
await page.goto("/");
await page.locator('[href="/rewrite"]').click();

await page.waitForURL("/rewrite");
let el = page.getByText("Rewritten Destination", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("a: b", { exact: true });
await expect(el).toBeVisible();
// Loading page should also rewrite
await page.goto("/rewrite");
await page.waitForURL("/rewrite");
el = page.getByText("Rewritten Destination", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("a: b", { exact: true });
await expect(el).toBeVisible();
await page.waitForURL("/rewrite");
let el = page.getByText("Rewritten Destination", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("a: b", { exact: true });
await expect(el).toBeVisible();
// Loading page should also rewrite
await page.goto("/rewrite");
await page.waitForURL("/rewrite");
el = page.getByText("Rewritten Destination", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("a: b", { exact: true });
await expect(el).toBeVisible();
});

test("Middleware Rewrite with multiple search params", async ({ page }) => {
await page.goto("/rewrite-multi-params");
let el = page.getByText("Rewritten Destination", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("a: b", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("multi: 0, 1, 2", { exact: true });
await expect(el).toBeVisible();
});

test("Middleware Rewrite should override original search params", async ({ page }) => {
await page.goto("/rewrite?a=1&multi=3");
let el = page.getByText("Rewritten Destination", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("a: b", { exact: true });
await expect(el).toBeVisible();
el = page.getByText("multi:", { exact: true });
await expect(el).toBeVisible();
await expect(el).toHaveText("multi:");
});
});
21 changes: 21 additions & 0 deletions examples/e2e/app-pages-router/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export function middleware(request: NextRequest) {
u.searchParams.set("a", "b");
return NextResponse.rewrite(u);
}
if (path === "/rewrite-multi-params") {
const u = new URL("/rewrite-destination", `${protocol}://${host}`);
u.searchParams.append("multi", "0");
u.searchParams.append("multi", "1");
u.searchParams.append("multi", "2");
u.searchParams.set("a", "b");
return NextResponse.rewrite(u);
}
if (path === "/api/middleware") {
return new NextResponse(JSON.stringify({ hello: "middleware" }), {
status: 200,
Expand All @@ -43,6 +51,19 @@ export function middleware(request: NextRequest) {
},
});
}

if (path === "/head" && request.method === "HEAD") {
return new NextResponse(null, {
headers: {
"x-from-middleware": "true",
},
});
}

if (path === "/fetch") {
// This one test both that we don't modify immutable headers
return fetch(new URL("/api/hello", request.url));
}
const rHeaders = new Headers(request.headers);
const r = NextResponse.next({
request: {
Expand Down
7 changes: 7 additions & 0 deletions examples/e2e/app-router/app/cookies/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { cookies } from "next/headers";

export default async function Page() {
const foo = (await cookies()).get("foo")?.value;

return <div data-testid="foo">{foo}</div>;
}
38 changes: 31 additions & 7 deletions examples/e2e/app-router/e2e/middleware.cookies.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
import { expect, test } from "@playwright/test";

test("Cookies", async ({ page, context }) => {
await page.goto("/");
test.describe("Middleware Cookies", () => {
test("should be able to set cookies on response in middleware", async ({ page, context }) => {
await page.goto("/");

const cookies = await context.cookies();
const from = cookies.find(({ name }) => name === "from");
expect(from?.value).toEqual("middleware");
const cookies = await context.cookies();
const from = cookies.find(({ name }) => name === "from");
expect(from?.value).toEqual("middleware");

const love = cookies.find(({ name }) => name === "with");
expect(love?.value).toEqual("love");
const love = cookies.find(({ name }) => name === "with");
expect(love?.value).toEqual("love");
});
test("should be able to get cookies set in the middleware with Next's cookies().get()", async ({
page,
}) => {
await page.goto("/cookies");

expect(await page.getByTestId("foo").textContent()).toBe("bar");
});
test("should not expose internal Next headers in response", async ({ page, context }) => {
const responsePromise = page.waitForResponse((response) => response.url().includes("/cookies"));

await page.goto("/cookies");

const response = await responsePromise;
const headers = response.headers();

const cookies = await context.cookies();
const fooCookie = cookies.find(({ name }) => name === "foo");
expect(fooCookie?.value).toBe("bar");

expect(headers).not.toHaveProperty("x-middleware-set-cookie");
expect(headers).not.toHaveProperty("x-middleware-next");
});
});
5 changes: 5 additions & 0 deletions examples/e2e/app-router/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export function middleware(request: NextRequest) {
const u = new URL("https://opennext.js.org/share.png");
return NextResponse.rewrite(u);
}
if (path === "/cookies") {
const res = NextResponse.next();
res.cookies.set("foo", "bar");
return res;
}
const requestHeaders = new Headers(request.headers);
// Setting the Request Headers, this should be available in RSC
requestHeaders.set("request-header", "request-header");
Expand Down
40 changes: 40 additions & 0 deletions examples/e2e/pages-router/e2e/fallback.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { expect, test } from "@playwright/test";

test.describe("fallback", () => {
test("should work with fully static fallback", async ({ page }) => {
await page.goto("/fallback-intercepted/static/");
const h1 = page.locator("h1");
await expect(h1).toHaveText("Static Fallback Page");
const p = page.getByTestId("message");
await expect(p).toHaveText("This is a fully static page.");
});

test("should work with static fallback", async ({ page }) => {
await page.goto("/fallback-intercepted/ssg/");
const h1 = page.locator("h1");
await expect(h1).toHaveText("Static Fallback Page");
const p = page.getByTestId("message");
await expect(p).toHaveText("This is a static ssg page.");
});

test("should work with fallback intercepted by dynamic route", async ({ page }) => {
await page.goto("/fallback-intercepted/something/");
const h1 = page.locator("h1");
await expect(h1).toHaveText("Dynamic Fallback Page");
const p = page.getByTestId("message");
await expect(p).toHaveText("This is a dynamic fallback page.");
});

test("should work with fallback page pregenerated", async ({ page }) => {
await page.goto("/fallback-intercepted/fallback/");
const h1 = page.locator("h1");
await expect(h1).toHaveText("Static Fallback Page");
const p = page.getByTestId("message");
await expect(p).toHaveText("This is a static fallback page.");
});

test("should 404 on page not pregenerated", async ({ request }) => {
const res = await request.get("/fallback/not-generated");
expect(res.status()).toBe(404);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { InferGetServerSidePropsType } from "next";

export function getServerSideProps() {
return {
props: {
message: "This is a dynamic fallback page.",
},
};
}

export default function Page({ message }: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<div>
<h1>Dynamic Fallback Page</h1>
<p data-testid="message">{message}</p>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { InferGetStaticPropsType } from "next";

export function getStaticPaths() {
return {
paths: [
{
params: {
slug: "fallback",
},
},
],
fallback: false,
};
}

export function getStaticProps() {
return {
props: {
message: "This is a static fallback page.",
},
};
}

export default function Page({ message }: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<div>
<h1>Static Fallback Page</h1>
<p data-testid="message">{message}</p>
</div>
);
}
18 changes: 18 additions & 0 deletions examples/e2e/pages-router/src/pages/fallback-intercepted/ssg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { InferGetStaticPropsType } from "next";

export function getStaticProps() {
return {
props: {
message: "This is a static ssg page.",
},
};
}

export default function Page({ message }: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<div>
<h1>Static Fallback Page</h1>
<p data-testid="message">{message}</p>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function Page() {
return (
<div>
<h1>Static Fallback Page</h1>
<p data-testid="message">This is a fully static page.</p>
</div>
);
}
31 changes: 31 additions & 0 deletions examples/e2e/pages-router/src/pages/fallback/[slug].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { InferGetStaticPropsType } from "next";

export function getStaticPaths() {
return {
paths: [
{
params: {
slug: "fallback",
},
},
],
fallback: false,
};
}

export function getStaticProps() {
return {
props: {
message: "This is a static fallback page.",
},
};
}

export default function Page({ message }: InferGetStaticPropsType<typeof getStaticProps>) {
return (
<div>
<h1>Static Fallback Page</h1>
<p data-testid="message">{message}</p>
</div>
);
}
2 changes: 1 addition & 1 deletion packages/cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"homepage": "https://github.com/opennextjs/opennextjs-cloudflare",
"dependencies": {
"@dotenvx/dotenvx": "catalog:",
"@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@859",
"@opennextjs/aws": "^3.6.1",
"enquirer": "^2.4.1",
"glob": "catalog:",
"ts-tqdm": "^0.8.6"
Expand Down
Loading