Skip to content
2 changes: 2 additions & 0 deletions packages/cloudflare/src/cli/build/bundle-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ export async function bundleServer(buildOpts: BuildOptions, projectOpts: Project
"process.env.TURBOPACK": "false",
// This define should be safe to use for Next 14.2+, earlier versions (13.5 and less) will cause trouble
"process.env.__NEXT_EXPERIMENTAL_REACT": `${needsExperimentalReact(nextConfig)}`,
// Fix `res.validate` in Next 15.4 (together with the `route-module` patch)
"process.env.__NEXT_TRUST_HOST_HEADER": "true",
},
banner: {
// We need to import them here, assigning them to `globalThis` does not work because node:timers use `globalThis` and thus create an infinite loop
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from "vitest";

import { computePatchDiff } from "../../utils/test-patch.js";
import { getIncrementalCacheRule } from "./route-module.js";
import { forceTrustHostHeader, getIncrementalCacheRule } from "./route-module.js";

const code = `class n9 {
constructor({ userland: e10, definition: t10, distDir: r10, projectDir: n10 }) {
Expand Down Expand Up @@ -380,3 +380,51 @@ test("patch the createSnapshot function", () => {
"
`);
});

test("force trustHostHeader to true", () => {
const code = `
async function e9(e, t, r, n) {
o.push("x-vercel-protection-bypass");
try {
if (n.trustHostHeader) {
let n = await fetch(\`https://\${r.headers.host}\${e}\`, {
method: "HEAD",
headers: s
});
} else {
throw Object.defineProperty(Error("Invariant: missing internal router-server-methods this is an internal bug"), "__NEXT_ERROR_CODE", {
value: "E676",
enumerable: !1,
configurable: !0
})
}
} catch (t) {
throw Object.defineProperty(Error(\`Failed to revalidate \${e}: \${e4(t)?t.message:t}\`), "__NEXT_ERROR_CODE", {
value: "E240",
enumerable: !1,
configurable: !0
})
}
}
`;

expect(computePatchDiff("pages-api.runtime.prod.js", code, forceTrustHostHeader)).toMatchInlineSnapshot(`
"Index: pages-api.runtime.prod.js
===================================================================
--- pages-api.runtime.prod.js
+++ pages-api.runtime.prod.js
@@ -1,8 +1,7 @@
-
-async function e9(e, t, r, n) {
- o.push("x-vercel-protection-bypass");
- try {
+async function e9(e,t,r,n) {
+ n.trustHostHeader = true;
+ o.push("x-vercel-protection-bypass");try {
if (n.trustHostHeader) {
let n = await fetch(\`https://\${r.headers.host}\${e}\`, {
method: "HEAD",
headers: s
"
`);
});
24 changes: 24 additions & 0 deletions packages/cloudflare/src/cli/build/patches/plugins/route-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export function patchRouteModules(updater: ContentUpdater, buildOpts: BuildOptio
const outputPath = path.join(outputDir, "server-functions/default");
const cacheHandler = path.join(outputPath, getPackagePath(buildOpts), "cache.cjs");
contents = patchCode(contents, getIncrementalCacheRule(cacheHandler));
contents = patchCode(contents, forceTrustHostHeader);
return contents;
},
},
Expand Down Expand Up @@ -59,3 +60,26 @@ fix: |-
let $CACHE_HANDLER = require('${normalizePath(handlerPath)}').default;
`;
}

/**
* Force trustHostHeader to be true for revalidation
*/
export const forceTrustHostHeader = `
rule:
pattern: async function $FN($$$ARGS) { $$$BODY }
all:
- has:
pattern: if ($CONTEXT.trustHostHeader) { $$$_ }
stopBy: end
- has:
regex: "^x-vercel-protection-bypass$"
stopBy: end
- has:
regex: "Invariant: missing internal"
stopBy: end
fix: |-
async function $FN($$$ARGS) {
$CONTEXT.trustHostHeader = true;
$$$BODY
}
`;