@netlify/plugin-nextjs 5.10.0-fetch-patch-logs → 5.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/build/advanced-api-routes.js +136 -4
  2. package/dist/build/cache.js +25 -4
  3. package/dist/build/content/prerendered.js +293 -11
  4. package/dist/build/content/server.js +219 -11
  5. package/dist/build/content/static.js +112 -15
  6. package/dist/build/functions/edge.js +540 -7
  7. package/dist/build/functions/server.js +130 -11
  8. package/dist/build/image-cdn.js +1599 -3
  9. package/dist/build/plugin-context.js +292 -6
  10. package/dist/build/verification.js +104 -9
  11. package/dist/esm-chunks/{package-F536DQ6H.js → package-UN6EVEHD.js} +1 -1
  12. package/dist/index.js +18 -39
  13. package/dist/run/config.js +1 -4
  14. package/dist/run/constants.js +7 -5
  15. package/dist/run/handlers/cache.cjs +44 -1655
  16. package/dist/run/handlers/server.js +14 -33
  17. package/dist/run/handlers/tracer.cjs +2 -114
  18. package/dist/run/handlers/tracing.js +2 -4
  19. package/dist/run/handlers/wait-until.cjs +2 -116
  20. package/dist/run/headers.js +198 -10
  21. package/dist/run/next.cjs +11 -1624
  22. package/dist/run/regional-blob-store.cjs +37 -5
  23. package/dist/run/revalidate.js +24 -3
  24. package/dist/shared/blobkey.js +15 -3
  25. package/package.json +1 -1
  26. package/dist/esm-chunks/chunk-3RQSTU2O.js +0 -554
  27. package/dist/esm-chunks/chunk-72ZI2IVI.js +0 -36
  28. package/dist/esm-chunks/chunk-AMY4NOT5.js +0 -1610
  29. package/dist/esm-chunks/chunk-DLVROEVU.js +0 -144
  30. package/dist/esm-chunks/chunk-GFYWJNQR.js +0 -305
  31. package/dist/esm-chunks/chunk-HXVWGXWM.js +0 -218
  32. package/dist/esm-chunks/chunk-IJZEDP6B.js +0 -235
  33. package/dist/esm-chunks/chunk-JPTD4GEB.js +0 -309
  34. package/dist/esm-chunks/chunk-MKMK7FBF.js +0 -132
  35. package/dist/esm-chunks/chunk-RYJYZQ4X.js +0 -610
  36. package/dist/esm-chunks/chunk-SGXRYMYQ.js +0 -127
  37. package/dist/esm-chunks/chunk-TYCYFZ22.js +0 -25
  38. package/dist/esm-chunks/chunk-UYKENJEU.js +0 -19
  39. package/dist/esm-chunks/chunk-WHUPSPWV.js +0 -73
  40. package/dist/esm-chunks/chunk-XS27YRA5.js +0 -34
  41. package/dist/esm-chunks/chunk-ZENB67PD.js +0 -148
  42. package/dist/esm-chunks/chunk-ZSVHJNNY.js +0 -120
  43. package/dist/esm-chunks/next-LDOXJ7XH.js +0 -567
@@ -1,144 +0,0 @@
1
-
2
- var require = await (async () => {
3
- var { createRequire } = await import("node:module");
4
- return createRequire(import.meta.url);
5
- })();
6
-
7
- import {
8
- copyNextDependencies,
9
- copyNextServerCode,
10
- verifyHandlerDirStructure
11
- } from "./chunk-IJZEDP6B.js";
12
- import {
13
- wrapTracer
14
- } from "./chunk-5QSXBV7L.js";
15
- import {
16
- init_esm,
17
- trace
18
- } from "./chunk-GNGHTHMQ.js";
19
- import {
20
- SERVER_HANDLER_NAME
21
- } from "./chunk-GFYWJNQR.js";
22
- import {
23
- require_out
24
- } from "./chunk-KGYJQ2U2.js";
25
- import {
26
- __toESM
27
- } from "./chunk-OEQOKJGE.js";
28
-
29
- // src/build/functions/server.ts
30
- init_esm();
31
- import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
32
- import { join, relative } from "node:path";
33
- import { join as posixJoin } from "node:path/posix";
34
- var import_fast_glob = __toESM(require_out(), 1);
35
- var tracer = wrapTracer(trace.getTracer("Next runtime"));
36
- var copyHandlerDependencies = async (ctx) => {
37
- await tracer.withActiveSpan("copyHandlerDependencies", async (span) => {
38
- const promises = [];
39
- const { included_files: includedFiles = [] } = ctx.netlifyConfig.functions?.["*"] || {};
40
- includedFiles.push(
41
- posixJoin(ctx.relativeAppDir, ".env"),
42
- posixJoin(ctx.relativeAppDir, ".env.production"),
43
- posixJoin(ctx.relativeAppDir, ".env.local"),
44
- posixJoin(ctx.relativeAppDir, ".env.production.local")
45
- );
46
- span.setAttribute("next.includedFiles", includedFiles.join(","));
47
- const resolvedFiles = await Promise.all(
48
- includedFiles.map((globPattern) => (0, import_fast_glob.glob)(globPattern, { cwd: process.cwd() }))
49
- );
50
- for (const filePath of resolvedFiles.flat()) {
51
- promises.push(
52
- cp(
53
- join(process.cwd(), filePath),
54
- // the serverHandlerDir is aware of the dist dir.
55
- // The distDir must not be the package path therefore we need to rely on the
56
- // serverHandlerDir instead of the serverHandlerRootDir
57
- // therefore we need to remove the package path from the filePath
58
- join(ctx.serverHandlerDir, relative(ctx.relativeAppDir, filePath)),
59
- {
60
- recursive: true,
61
- force: true
62
- }
63
- )
64
- );
65
- }
66
- promises.push(
67
- writeFile(
68
- join(ctx.serverHandlerRuntimeModulesDir, "package.json"),
69
- JSON.stringify({ type: "module" })
70
- )
71
- );
72
- const fileList = await (0, import_fast_glob.glob)("dist/**/*", { cwd: ctx.pluginDir });
73
- for (const filePath of fileList) {
74
- promises.push(
75
- cp(join(ctx.pluginDir, filePath), join(ctx.serverHandlerRuntimeModulesDir, filePath), {
76
- recursive: true,
77
- force: true
78
- })
79
- );
80
- }
81
- await Promise.all(promises);
82
- });
83
- };
84
- var writeHandlerManifest = async (ctx) => {
85
- await writeFile(
86
- join(ctx.serverHandlerRootDir, `${SERVER_HANDLER_NAME}.json`),
87
- JSON.stringify({
88
- config: {
89
- name: "Next.js Server Handler",
90
- generator: `${ctx.pluginName}@${ctx.pluginVersion}`,
91
- nodeBundler: "none",
92
- // the folders can vary in monorepos based on the folder structure of the user so we have to glob all
93
- includedFiles: ["**"],
94
- includedFilesBasePath: ctx.serverHandlerRootDir
95
- },
96
- version: 1
97
- }),
98
- "utf-8"
99
- );
100
- };
101
- var applyTemplateVariables = (template, variables) => {
102
- return Object.entries(variables).reduce((acc, [key, value]) => {
103
- return acc.replaceAll(key, value);
104
- }, template);
105
- };
106
- var getHandlerFile = async (ctx) => {
107
- const templatesDir = join(ctx.pluginDir, "dist/build/templates");
108
- const templateVariables = {
109
- "{{useRegionalBlobs}}": ctx.useRegionalBlobs.toString()
110
- };
111
- if (ctx.relativeAppDir.length !== 0) {
112
- const template = await readFile(join(templatesDir, "handler-monorepo.tmpl.js"), "utf-8");
113
- templateVariables["{{cwd}}"] = posixJoin(ctx.lambdaWorkingDirectory);
114
- templateVariables["{{nextServerHandler}}"] = posixJoin(ctx.nextServerHandler);
115
- return applyTemplateVariables(template, templateVariables);
116
- }
117
- return applyTemplateVariables(
118
- await readFile(join(templatesDir, "handler.tmpl.js"), "utf-8"),
119
- templateVariables
120
- );
121
- };
122
- var writeHandlerFile = async (ctx) => {
123
- const handler = await getHandlerFile(ctx);
124
- await writeFile(join(ctx.serverHandlerRootDir, `${SERVER_HANDLER_NAME}.mjs`), handler);
125
- };
126
- var clearStaleServerHandlers = async (ctx) => {
127
- await rm(ctx.serverFunctionsDir, { recursive: true, force: true });
128
- };
129
- var createServerHandler = async (ctx) => {
130
- await tracer.withActiveSpan("createServerHandler", async () => {
131
- await mkdir(join(ctx.serverHandlerRuntimeModulesDir), { recursive: true });
132
- await copyNextServerCode(ctx);
133
- await copyNextDependencies(ctx);
134
- await copyHandlerDependencies(ctx);
135
- await writeHandlerManifest(ctx);
136
- await writeHandlerFile(ctx);
137
- await verifyHandlerDirStructure(ctx);
138
- });
139
- };
140
-
141
- export {
142
- clearStaleServerHandlers,
143
- createServerHandler
144
- };
@@ -1,305 +0,0 @@
1
-
2
- var require = await (async () => {
3
- var { createRequire } = await import("node:module");
4
- return createRequire(import.meta.url);
5
- })();
6
-
7
- import {
8
- require_semver
9
- } from "./chunk-APO262HE.js";
10
- import {
11
- __toESM
12
- } from "./chunk-OEQOKJGE.js";
13
-
14
- // src/build/plugin-context.ts
15
- var import_semver = __toESM(require_semver(), 1);
16
- import { existsSync, readFileSync } from "node:fs";
17
- import { readFile } from "node:fs/promises";
18
- import { createRequire } from "node:module";
19
- import { join, relative, resolve } from "node:path";
20
- import { join as posixJoin } from "node:path/posix";
21
- import { fileURLToPath } from "node:url";
22
- var MODULE_DIR = fileURLToPath(new URL(".", import.meta.url));
23
- var PLUGIN_DIR = join(MODULE_DIR, "../..");
24
- var DEFAULT_PUBLISH_DIR = ".next";
25
- var SERVER_HANDLER_NAME = "___netlify-server-handler";
26
- var EDGE_HANDLER_NAME = "___netlify-edge-handler";
27
- var PluginContext = class {
28
- featureFlags;
29
- netlifyConfig;
30
- pluginName;
31
- pluginVersion;
32
- utils;
33
- constants;
34
- packageJSON;
35
- /** Absolute path of the next runtime plugin directory */
36
- pluginDir = PLUGIN_DIR;
37
- get relPublishDir() {
38
- return this.constants.PUBLISH_DIR ?? join(this.constants.PACKAGE_PATH || "", DEFAULT_PUBLISH_DIR);
39
- }
40
- /** Temporary directory for stashing the build output */
41
- get tempPublishDir() {
42
- return this.resolveFromPackagePath(".netlify/.next");
43
- }
44
- /** Absolute path of the publish directory */
45
- get publishDir() {
46
- return resolve(this.relPublishDir);
47
- }
48
- /**
49
- * Relative package path in non monorepo setups this is an empty string
50
- * This path is provided by Next.js RequiredServerFiles manifest
51
- * @example ''
52
- * @example 'apps/my-app'
53
- */
54
- get relativeAppDir() {
55
- return this.requiredServerFiles.relativeAppDir ?? "";
56
- }
57
- /**
58
- * The working directory inside the lambda that is used for monorepos to execute the serverless function
59
- */
60
- get lambdaWorkingDirectory() {
61
- return join("/var/task", this.distDirParent);
62
- }
63
- /**
64
- * Retrieves the root of the `.next/standalone` directory
65
- */
66
- get standaloneRootDir() {
67
- return join(this.publishDir, "standalone");
68
- }
69
- /**
70
- * The resolved relative next dist directory defaults to `.next`,
71
- * but can be configured through the next.config.js. For monorepos this will include the packagePath
72
- * If we need just the plain dist dir use the `nextDistDir`
73
- */
74
- get distDir() {
75
- const dir = this.buildConfig.distDir ?? DEFAULT_PUBLISH_DIR;
76
- return relative(process.cwd(), resolve(this.relativeAppDir, dir));
77
- }
78
- /** Represents the parent directory of the .next folder or custom distDir */
79
- get distDirParent() {
80
- return join(this.distDir, "..");
81
- }
82
- /** The `.next` folder or what the custom dist dir is set to */
83
- get nextDistDir() {
84
- return relative(this.distDirParent, this.distDir);
85
- }
86
- /** Retrieves the `.next/standalone/` directory monorepo aware */
87
- get standaloneDir() {
88
- return join(this.standaloneRootDir, this.distDirParent);
89
- }
90
- /**
91
- * Absolute path of the directory that is published and deployed to the Netlify CDN
92
- * Will be swapped with the publish directory
93
- * `.netlify/static`
94
- */
95
- get staticDir() {
96
- return this.resolveFromPackagePath(".netlify/static");
97
- }
98
- /**
99
- * Absolute path of the directory that will be deployed to the blob store
100
- * region aware: `.netlify/deploy/v1/blobs/deploy`
101
- * default: `.netlify/blobs/deploy`
102
- */
103
- get blobDir() {
104
- if (this.useRegionalBlobs) {
105
- return this.resolveFromPackagePath(".netlify/deploy/v1/blobs/deploy");
106
- }
107
- return this.resolveFromPackagePath(".netlify/blobs/deploy");
108
- }
109
- get buildVersion() {
110
- return this.constants.NETLIFY_BUILD_VERSION || "v0.0.0";
111
- }
112
- get useRegionalBlobs() {
113
- const REQUIRED_BUILD_VERSION = ">=29.41.5";
114
- return (0, import_semver.satisfies)(this.buildVersion, REQUIRED_BUILD_VERSION, { includePrerelease: true });
115
- }
116
- /**
117
- * Absolute path of the directory containing the files for the serverless lambda function
118
- * `.netlify/functions-internal`
119
- */
120
- get serverFunctionsDir() {
121
- return this.resolveFromPackagePath(".netlify/functions-internal");
122
- }
123
- /** Absolute path of the server handler */
124
- get serverHandlerRootDir() {
125
- return join(this.serverFunctionsDir, SERVER_HANDLER_NAME);
126
- }
127
- get serverHandlerDir() {
128
- if (this.relativeAppDir.length === 0) {
129
- return this.serverHandlerRootDir;
130
- }
131
- return join(this.serverHandlerRootDir, this.distDirParent);
132
- }
133
- get serverHandlerRuntimeModulesDir() {
134
- return join(this.serverHandlerDir, ".netlify");
135
- }
136
- get nextServerHandler() {
137
- if (this.relativeAppDir.length !== 0) {
138
- return join(this.lambdaWorkingDirectory, ".netlify/dist/run/handlers/server.js");
139
- }
140
- return "./.netlify/dist/run/handlers/server.js";
141
- }
142
- /**
143
- * Absolute path of the directory containing the files for deno edge functions
144
- * `.netlify/edge-functions`
145
- */
146
- get edgeFunctionsDir() {
147
- return this.resolveFromPackagePath(".netlify/edge-functions");
148
- }
149
- /** Absolute path of the edge handler */
150
- get edgeHandlerDir() {
151
- return join(this.edgeFunctionsDir, EDGE_HANDLER_NAME);
152
- }
153
- constructor(options) {
154
- this.constants = options.constants;
155
- this.featureFlags = options.featureFlags;
156
- this.netlifyConfig = options.netlifyConfig;
157
- this.packageJSON = JSON.parse(readFileSync(join(PLUGIN_DIR, "package.json"), "utf-8"));
158
- this.pluginName = this.packageJSON.name;
159
- this.pluginVersion = this.packageJSON.version;
160
- this.utils = options.utils;
161
- }
162
- /** Resolves a path correctly with mono repository awareness for .netlify directories mainly */
163
- resolveFromPackagePath(...args) {
164
- return resolve(this.constants.PACKAGE_PATH || "", ...args);
165
- }
166
- /** Resolves a path correctly from site directory */
167
- resolveFromSiteDir(...args) {
168
- return resolve(this.requiredServerFiles.appDir, ...args);
169
- }
170
- /** Get the next prerender-manifest.json */
171
- async getPrerenderManifest() {
172
- return JSON.parse(await readFile(join(this.publishDir, "prerender-manifest.json"), "utf-8"));
173
- }
174
- /**
175
- * Uses various heuristics to try to find the .next dir.
176
- * Works by looking for BUILD_ID, so requires the site to have been built
177
- */
178
- findDotNext() {
179
- for (const dir of [
180
- // The publish directory
181
- this.publishDir,
182
- // In the root
183
- resolve(DEFAULT_PUBLISH_DIR),
184
- // The sibling of the publish directory
185
- resolve(this.publishDir, "..", DEFAULT_PUBLISH_DIR),
186
- // In the package dir
187
- resolve(this.constants.PACKAGE_PATH || "", DEFAULT_PUBLISH_DIR)
188
- ]) {
189
- if (existsSync(join(dir, "BUILD_ID"))) {
190
- return dir;
191
- }
192
- }
193
- return false;
194
- }
195
- /**
196
- * Get Next.js middleware config from the build output
197
- */
198
- async getMiddlewareManifest() {
199
- return JSON.parse(
200
- await readFile(join(this.publishDir, "server/middleware-manifest.json"), "utf-8")
201
- );
202
- }
203
- // don't make private as it is handy inside testing to override the config
204
- _requiredServerFiles = null;
205
- /** Get RequiredServerFiles manifest from build output **/
206
- get requiredServerFiles() {
207
- if (!this._requiredServerFiles) {
208
- let requiredServerFilesJson = join(this.publishDir, "required-server-files.json");
209
- if (!existsSync(requiredServerFilesJson)) {
210
- const dotNext = this.findDotNext();
211
- if (dotNext) {
212
- requiredServerFilesJson = join(dotNext, "required-server-files.json");
213
- }
214
- }
215
- this._requiredServerFiles = JSON.parse(
216
- readFileSync(requiredServerFilesJson, "utf-8")
217
- );
218
- }
219
- return this._requiredServerFiles;
220
- }
221
- #exportDetail = null;
222
- /** Get metadata when output = export */
223
- get exportDetail() {
224
- if (this.buildConfig.output !== "export") {
225
- return null;
226
- }
227
- if (!this.#exportDetail) {
228
- const detailFile = join(
229
- this.requiredServerFiles.appDir,
230
- this.buildConfig.distDir,
231
- "export-detail.json"
232
- );
233
- if (!existsSync(detailFile)) {
234
- return null;
235
- }
236
- try {
237
- this.#exportDetail = JSON.parse(readFileSync(detailFile, "utf-8"));
238
- } catch {
239
- }
240
- }
241
- return this.#exportDetail;
242
- }
243
- /** Get Next Config from build output **/
244
- get buildConfig() {
245
- return this.requiredServerFiles.config;
246
- }
247
- /**
248
- * Get Next.js routes manifest from the build output
249
- */
250
- async getRoutesManifest() {
251
- return JSON.parse(await readFile(join(this.publishDir, "routes-manifest.json"), "utf-8"));
252
- }
253
- #nextVersion = void 0;
254
- /**
255
- * Get Next.js version that was used to build the site
256
- */
257
- get nextVersion() {
258
- if (this.#nextVersion === void 0) {
259
- try {
260
- const serverHandlerRequire = createRequire(posixJoin(this.standaloneRootDir, ":internal:"));
261
- const { version } = serverHandlerRequire("next/package.json");
262
- this.#nextVersion = version;
263
- } catch {
264
- this.#nextVersion = null;
265
- }
266
- }
267
- return this.#nextVersion;
268
- }
269
- #fallbacks = null;
270
- /**
271
- * Get an array of localized fallback routes
272
- *
273
- * Example return value for non-i18n site: `['blog/[slug]']`
274
- *
275
- * Example return value for i18n site: `['en/blog/[slug]', 'fr/blog/[slug]']`
276
- */
277
- getFallbacks(prerenderManifest) {
278
- if (!this.#fallbacks) {
279
- const locales = this.buildConfig.i18n?.locales ?? [""];
280
- this.#fallbacks = Object.entries(prerenderManifest.dynamicRoutes).reduce(
281
- (fallbacks, [route, meta]) => {
282
- if (typeof meta.fallback === "string") {
283
- for (const locale of locales) {
284
- const localizedRoute = posixJoin(locale, route.replace(/^\/+/g, ""));
285
- fallbacks.push(localizedRoute);
286
- }
287
- }
288
- return fallbacks;
289
- },
290
- []
291
- );
292
- }
293
- return this.#fallbacks;
294
- }
295
- /** Fails a build with a message and an optional error */
296
- failBuild(message, error) {
297
- return this.utils.build.failBuild(message, error instanceof Error ? { error } : void 0);
298
- }
299
- };
300
-
301
- export {
302
- SERVER_HANDLER_NAME,
303
- EDGE_HANDLER_NAME,
304
- PluginContext
305
- };
@@ -1,218 +0,0 @@
1
-
2
- var require = await (async () => {
3
- var { createRequire } = await import("node:module");
4
- return createRequire(import.meta.url);
5
- })();
6
-
7
- import {
8
- getRegionalBlobStore
9
- } from "./chunk-RYJYZQ4X.js";
10
- import {
11
- getLogger
12
- } from "./chunk-SGXRYMYQ.js";
13
- import {
14
- encodeBlobKey
15
- } from "./chunk-TYCYFZ22.js";
16
-
17
- // src/run/headers.ts
18
- var ALL_VARIATIONS = Symbol.for("ALL_VARIATIONS");
19
- var NetlifyVaryKeys = /* @__PURE__ */ new Set(["header", "language", "cookie", "query", "country"]);
20
- var isNetlifyVaryKey = (key) => NetlifyVaryKeys.has(key);
21
- var generateNetlifyVaryValues = ({
22
- header,
23
- language,
24
- cookie,
25
- query,
26
- country
27
- }) => {
28
- const values = [];
29
- if (query.length !== 0) {
30
- if (query.includes(ALL_VARIATIONS)) {
31
- values.push(`query`);
32
- } else {
33
- values.push(`query=${query.join(`|`)}`);
34
- }
35
- }
36
- if (header.length !== 0) {
37
- values.push(`header=${header.join(`|`)}`);
38
- }
39
- if (language.length !== 0) {
40
- values.push(`language=${language.join(`|`)}`);
41
- }
42
- if (cookie.length !== 0) {
43
- values.push(`cookie=${cookie.join(`|`)}`);
44
- }
45
- if (country.length !== 0) {
46
- values.push(`country=${country.join(`|`)}`);
47
- }
48
- return values.join(",");
49
- };
50
- var getHeaderValueArray = (header) => {
51
- return header.split(",").map((value) => value.trim()).filter(Boolean);
52
- };
53
- var omitHeaderValues = (header, values) => {
54
- const headerValues = getHeaderValueArray(header);
55
- const filteredValues = headerValues.filter(
56
- (value) => !values.some((val) => value.startsWith(val))
57
- );
58
- return filteredValues.join(", ");
59
- };
60
- var setVaryHeaders = (headers, request, { basePath, i18n }) => {
61
- const netlifyVaryValues = {
62
- header: ["x-nextjs-data", "x-next-debug-logging"],
63
- language: [],
64
- cookie: ["__prerender_bypass", "__next_preview_data"],
65
- query: ["__nextDataReq"],
66
- country: []
67
- };
68
- const vary = headers.get("vary");
69
- if (vary !== null) {
70
- netlifyVaryValues.header.push(...getHeaderValueArray(vary));
71
- }
72
- const path = new URL(request.url).pathname;
73
- const locales = i18n && i18n.localeDetection !== false ? i18n.locales : [];
74
- if (locales.length > 1 && (path === "/" || path === basePath)) {
75
- netlifyVaryValues.language.push(...locales);
76
- netlifyVaryValues.cookie.push(`NEXT_LOCALE`);
77
- }
78
- const userNetlifyVary = headers.get("netlify-vary");
79
- if (userNetlifyVary) {
80
- const directives = getHeaderValueArray(userNetlifyVary);
81
- for (const directive of directives) {
82
- const [key, value] = directive.split("=");
83
- if (key === "query" && !value) {
84
- netlifyVaryValues.query.push(ALL_VARIATIONS);
85
- } else if (value && isNetlifyVaryKey(key)) {
86
- netlifyVaryValues[key].push(...value.split("|"));
87
- }
88
- }
89
- }
90
- headers.set(`netlify-vary`, generateNetlifyVaryValues(netlifyVaryValues));
91
- };
92
- var adjustDateHeader = async ({
93
- headers,
94
- request,
95
- span,
96
- tracer,
97
- requestContext
98
- }) => {
99
- const key = new URL(request.url).pathname;
100
- let lastModified;
101
- if (requestContext.responseCacheGetLastModified) {
102
- lastModified = requestContext.responseCacheGetLastModified;
103
- } else {
104
- span.recordException(
105
- new Error("lastModified not found in requestContext, falling back to trying blobs")
106
- );
107
- span.setAttributes({
108
- severity: "alert",
109
- warning: true
110
- });
111
- const blobStore = getRegionalBlobStore({ consistency: "strong" });
112
- const blobKey = await encodeBlobKey(key);
113
- lastModified = await tracer.withActiveSpan(
114
- "get cache to calculate date header",
115
- async (getBlobForDateSpan) => {
116
- getBlobForDateSpan.setAttributes({
117
- key,
118
- blobKey
119
- });
120
- const blob = await blobStore.get(blobKey, { type: "json" }) ?? {};
121
- getBlobForDateSpan.addEvent(blob ? "Cache hit" : "Cache miss");
122
- return blob.lastModified;
123
- }
124
- );
125
- }
126
- if (!lastModified) {
127
- span.recordException(
128
- new Error(
129
- "lastModified not found in either requestContext or blobs, date header for cached response is not set"
130
- )
131
- );
132
- span.setAttributes({
133
- severity: "alert",
134
- warning: true
135
- });
136
- return;
137
- }
138
- const lastModifiedDate = new Date(lastModified);
139
- headers.set("x-nextjs-date", headers.get("date") ?? lastModifiedDate.toUTCString());
140
- headers.set("date", lastModifiedDate.toUTCString());
141
- };
142
- function setCacheControlFromRequestContext(headers, revalidate) {
143
- const cdnCacheControl = (
144
- // if we are serving already stale response, instruct edge to not attempt to cache that response
145
- headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate, durable" : `s-maxage=${revalidate || 31536e3}, stale-while-revalidate=31536000, durable`
146
- );
147
- headers.set("netlify-cdn-cache-control", cdnCacheControl);
148
- }
149
- var setCacheControlHeaders = ({ headers, status }, request, requestContext, nextConfig) => {
150
- if (typeof requestContext.routeHandlerRevalidate !== "undefined" && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
151
- setCacheControlFromRequestContext(headers, requestContext.routeHandlerRevalidate);
152
- return;
153
- }
154
- if (status === 308 && request.url.endsWith("/") !== nextConfig.trailingSlash) {
155
- getLogger().withFields({ trailingSlash: nextConfig.trailingSlash, location: headers.get("location") }).log("NetlifyHeadersHandler.trailingSlashRedirect");
156
- }
157
- const cacheControl = headers.get("cache-control");
158
- if (status === 404) {
159
- if (request.url.endsWith(".php")) {
160
- headers.set("cache-control", "public, max-age=0, must-revalidate");
161
- headers.set("netlify-cdn-cache-control", `max-age=31536000, durable`);
162
- return;
163
- }
164
- if (process.env.CACHE_404_PAGE && request.url.endsWith("/404") && ["GET", "HEAD"].includes(request.method)) {
165
- setCacheControlFromRequestContext(headers, requestContext.pageHandlerRevalidate);
166
- return;
167
- }
168
- }
169
- if (cacheControl !== null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
170
- const browserCacheControl = omitHeaderValues(cacheControl, [
171
- "s-maxage",
172
- "stale-while-revalidate"
173
- ]);
174
- const cdnCacheControl = (
175
- // if we are serving already stale response, instruct edge to not attempt to cache that response
176
- headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate, durable" : [
177
- ...getHeaderValueArray(cacheControl).map(
178
- (value) => value === "stale-while-revalidate" ? "stale-while-revalidate=31536000" : value
179
- ),
180
- "durable"
181
- ].join(", ")
182
- );
183
- headers.set("cache-control", browserCacheControl || "public, max-age=0, must-revalidate");
184
- headers.set("netlify-cdn-cache-control", cdnCacheControl);
185
- return;
186
- }
187
- if (cacheControl === null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control") && requestContext.usedFsReadForNonFallback) {
188
- headers.set("cache-control", "public, max-age=0, must-revalidate");
189
- headers.set("netlify-cdn-cache-control", `max-age=31536000, durable`);
190
- }
191
- };
192
- var setCacheTagsHeaders = (headers, requestContext) => {
193
- if (requestContext.responseCacheTags && (headers.has("cache-control") || headers.has("netlify-cdn-cache-control"))) {
194
- headers.set("netlify-cache-tag", requestContext.responseCacheTags.join(","));
195
- }
196
- };
197
- var NEXT_CACHE_TO_CACHE_STATUS = {
198
- HIT: `hit`,
199
- MISS: `fwd=miss`,
200
- STALE: `hit; fwd=stale`
201
- };
202
- var setCacheStatusHeader = (headers, nextCache) => {
203
- if (typeof nextCache === "string") {
204
- if (nextCache in NEXT_CACHE_TO_CACHE_STATUS) {
205
- const cacheStatus = NEXT_CACHE_TO_CACHE_STATUS[nextCache];
206
- headers.set("cache-status", `"Next.js"; ${cacheStatus}`);
207
- }
208
- headers.delete("x-nextjs-cache");
209
- }
210
- };
211
-
212
- export {
213
- setVaryHeaders,
214
- adjustDateHeader,
215
- setCacheControlHeaders,
216
- setCacheTagsHeaders,
217
- setCacheStatusHeader
218
- };