Skip to content

Commit ae31733

Browse files
authored
test: add tests for remotePatterns (#730)
1 parent 689327d commit ae31733

File tree

11 files changed

+530
-127
lines changed

11 files changed

+530
-127
lines changed

.changeset/bright-readers-love.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/cloudflare": patch
3+
---
4+
5+
add tests for remote patterns

examples/playground14/e2e/cloudflare.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,15 @@ test.describe("playground/cloudflare", () => {
1818
const res = await page.request.get("/api/env");
1919
await expect(res.json()).resolves.toEqual(expect.objectContaining({ PROCESS_ENV_VAR: "process.env" }));
2020
});
21+
22+
test("fetch an image allowed by remotePatterns", async ({ page }) => {
23+
const res = await page.request.get("/_next/image?url=https://avatars.githubusercontent.com/u/248818");
24+
expect(res.status()).toBe(200);
25+
expect(res.headers()).toMatchObject({ "content-type": "image/jpeg" });
26+
});
27+
28+
test("404 when fetching an image disallowed by remotePatterns", async ({ page }) => {
29+
const res = await page.request.get("/_next/image?url=https://avatars.githubusercontent.com/u/248817");
30+
expect(res.status()).toBe(400);
31+
});
2132
});

examples/playground14/next.config.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ const nextConfig = {
1111
serverSourceMaps: true,
1212
instrumentationHook: true,
1313
},
14+
images: {
15+
remotePatterns: [
16+
{
17+
protocol: "https",
18+
hostname: "avatars.githubusercontent.com",
19+
pathname: "/u/248818",
20+
},
21+
],
22+
},
1423
};
1524

1625
export default nextConfig;

packages/cloudflare/src/cli/build/build.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { compileCache } from "@opennextjs/aws/build/compileCache.js";
33
import { createCacheAssets, createStaticAssets } from "@opennextjs/aws/build/createAssets.js";
44
import { createMiddleware } from "@opennextjs/aws/build/createMiddleware.js";
55
import * as buildHelper from "@opennextjs/aws/build/helper.js";
6-
import { BuildOptions } from "@opennextjs/aws/build/helper.js";
76
import { printHeader } from "@opennextjs/aws/build/utils.js";
87
import logger from "@opennextjs/aws/logger.js";
98

@@ -12,6 +11,7 @@ import type { ProjectOptions } from "../project-options.js";
1211
import { bundleServer } from "./bundle-server.js";
1312
import { compileCacheAssetsManifestSqlFile } from "./open-next/compile-cache-assets-manifest.js";
1413
import { compileEnvFiles } from "./open-next/compile-env-files.js";
14+
import { compileImages } from "./open-next/compile-images.js";
1515
import { compileInit } from "./open-next/compile-init.js";
1616
import { compileDurableObjects } from "./open-next/compileDurableObjects.js";
1717
import { createServerBundle } from "./open-next/createServerBundle.js";
@@ -28,7 +28,7 @@ import { getVersion } from "./utils/version.js";
2828
* @param projectOpts The options for the project
2929
*/
3030
export async function build(
31-
options: BuildOptions,
31+
options: buildHelper.BuildOptions,
3232
config: OpenNextConfig,
3333
projectOpts: ProjectOptions
3434
): Promise<void> {
@@ -67,6 +67,9 @@ export async function build(
6767
// Compile workerd init
6868
compileInit(options);
6969

70+
// Compile image helpers
71+
compileImages(options);
72+
7073
// Compile middleware
7174
await createMiddleware(options, { forceOnlyBuildOnce: true });
7275

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
import { fileURLToPath } from "node:url";
4+
5+
import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
6+
import { build } from "esbuild";
7+
8+
/**
9+
* Compiles the initialization code for the workerd runtime
10+
*/
11+
export async function compileImages(options: BuildOptions) {
12+
const currentDir = path.join(path.dirname(fileURLToPath(import.meta.url)));
13+
const templatesDir = path.join(currentDir, "../../templates");
14+
const imagesPath = path.join(templatesDir, "images.js");
15+
16+
const imagesManifestPath = path.join(options.appBuildOutputPath, ".next/images-manifest.json");
17+
const imagesManifest = fs.existsSync(imagesManifestPath)
18+
? JSON.parse(fs.readFileSync(imagesManifestPath, { encoding: "utf-8" }))
19+
: {};
20+
21+
await build({
22+
entryPoints: [imagesPath],
23+
outdir: path.join(options.outputDir, "cloudflare"),
24+
bundle: false,
25+
minify: false,
26+
format: "esm",
27+
target: "esnext",
28+
platform: "node",
29+
define: {
30+
__IMAGES_REMOTE_PATTERNS__: JSON.stringify(imagesManifest?.images?.remotePatterns ?? []),
31+
__IMAGES_LOCAL_PATTERNS__: JSON.stringify(imagesManifest?.images?.localPatterns ?? []),
32+
},
33+
});
34+
}
Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
21
import path from "node:path";
32
import { fileURLToPath } from "node:url";
43

54
import { loadConfig } from "@opennextjs/aws/adapters/config/util.js";
65
import type { BuildOptions } from "@opennextjs/aws/build/helper.js";
76
import { build } from "esbuild";
8-
import pm from "picomatch";
97

108
/**
119
* Compiles the initialization code for the workerd runtime
@@ -18,27 +16,6 @@ export async function compileInit(options: BuildOptions) {
1816
const nextConfig = loadConfig(path.join(options.appBuildOutputPath, ".next"));
1917
const basePath = nextConfig.basePath ?? "";
2018

21-
// https://github.com/vercel/next.js/blob/d76f0b13/packages/next/src/build/index.ts#L573
22-
const nextRemotePatterns = nextConfig.images?.remotePatterns ?? [];
23-
24-
const remotePatterns = nextRemotePatterns.map((p) => ({
25-
protocol: p.protocol,
26-
hostname: p.hostname ? pm.makeRe(p.hostname).source : undefined,
27-
port: p.port,
28-
pathname: pm.makeRe(p.pathname ?? "**", { dot: true }).source,
29-
// search is canary only as of June 2025
30-
search: (p as any).search,
31-
}));
32-
33-
// Local patterns are only in canary as of June 2025
34-
const nextLocalPatterns = (nextConfig.images as any)?.localPatterns ?? [];
35-
36-
// https://github.com/vercel/next.js/blob/d76f0b13/packages/next/src/build/index.ts#L573
37-
const localPatterns = nextLocalPatterns.map((p: any) => ({
38-
pathname: pm.makeRe(p.pathname ?? "**", { dot: true }).source,
39-
search: p.search,
40-
}));
41-
4219
await build({
4320
entryPoints: [initPath],
4421
outdir: path.join(options.outputDir, "cloudflare"),
@@ -50,8 +27,6 @@ export async function compileInit(options: BuildOptions) {
5027
define: {
5128
__BUILD_TIMESTAMP_MS__: JSON.stringify(Date.now()),
5229
__NEXT_BASE_PATH__: JSON.stringify(basePath),
53-
__IMAGES_REMOTE_PATTERNS__: JSON.stringify(remotePatterns),
54-
__IMAGES_LOCAL_PATTERNS__: JSON.stringify(localPatterns),
5530
},
5631
});
5732
}

0 commit comments

Comments
 (0)