@cloudflare/pages-shared 0.13.71 → 0.13.72

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 (46) hide show
  1. package/dist/__tests__/asset-server/handler.test.d.ts +2 -0
  2. package/dist/__tests__/asset-server/handler.test.d.ts.map +1 -0
  3. package/dist/__tests__/asset-server/responses.test.d.ts +2 -0
  4. package/dist/__tests__/asset-server/responses.test.d.ts.map +1 -0
  5. package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts +2 -0
  6. package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts.map +1 -0
  7. package/dist/asset-server/handler.d.ts +62 -0
  8. package/dist/asset-server/handler.d.ts.map +1 -0
  9. package/dist/asset-server/handler.js +890 -0
  10. package/dist/asset-server/handler.js.map +7 -0
  11. package/dist/asset-server/metadata.d.ts +52 -0
  12. package/dist/asset-server/metadata.d.ts.map +1 -0
  13. package/dist/asset-server/metadata.js +0 -0
  14. package/dist/asset-server/metadata.js.map +7 -0
  15. package/dist/asset-server/patchUrl.d.ts +2 -0
  16. package/dist/asset-server/patchUrl.d.ts.map +1 -0
  17. package/dist/asset-server/patchUrl.js +15 -0
  18. package/dist/asset-server/patchUrl.js.map +7 -0
  19. package/dist/asset-server/responses.d.ts +45 -0
  20. package/dist/asset-server/responses.d.ts.map +1 -0
  21. package/dist/asset-server/responses.js +166 -0
  22. package/dist/asset-server/responses.js.map +7 -0
  23. package/dist/environment-polyfills/html-rewriter.d.ts +9 -0
  24. package/dist/environment-polyfills/html-rewriter.d.ts.map +1 -0
  25. package/dist/environment-polyfills/index.d.ts +3 -0
  26. package/dist/environment-polyfills/index.d.ts.map +1 -0
  27. package/dist/environment-polyfills/miniflare.d.ts +3 -0
  28. package/dist/environment-polyfills/miniflare.d.ts.map +1 -0
  29. package/dist/environment-polyfills/types.d.ts +11 -0
  30. package/dist/environment-polyfills/types.d.ts.map +1 -0
  31. package/dist/metadata-generator/constants.d.ts +14 -0
  32. package/dist/metadata-generator/constants.d.ts.map +1 -0
  33. package/dist/metadata-generator/constants.js +29 -0
  34. package/dist/metadata-generator/constants.js.map +7 -0
  35. package/dist/metadata-generator/createMetadataObject.d.ts +13 -0
  36. package/dist/metadata-generator/createMetadataObject.d.ts.map +1 -0
  37. package/dist/metadata-generator/createMetadataObject.js +174 -0
  38. package/dist/metadata-generator/createMetadataObject.js.map +7 -0
  39. package/dist/metadata-generator/types.d.ts +42 -0
  40. package/dist/metadata-generator/types.d.ts.map +1 -0
  41. package/dist/metadata-generator/types.js +0 -0
  42. package/dist/metadata-generator/types.js.map +7 -0
  43. package/dist/scripts/build.d.ts +2 -0
  44. package/dist/scripts/build.d.ts.map +1 -0
  45. package/dist/tsconfig.build.tsbuildinfo +1 -0
  46. package/package.json +10 -5
@@ -0,0 +1,890 @@
1
+ // ../workers-shared/utils/responses.ts
2
+ var OkResponse = class _OkResponse extends Response {
3
+ static {
4
+ this.status = 200;
5
+ }
6
+ constructor(body, init) {
7
+ super(body, {
8
+ ...init,
9
+ status: _OkResponse.status
10
+ });
11
+ }
12
+ };
13
+ var NotFoundResponse = class _NotFoundResponse extends Response {
14
+ static {
15
+ this.status = 404;
16
+ }
17
+ constructor(...[body, init]) {
18
+ super(body, {
19
+ ...init,
20
+ status: _NotFoundResponse.status,
21
+ statusText: "Not Found"
22
+ });
23
+ }
24
+ };
25
+ var MethodNotAllowedResponse = class _MethodNotAllowedResponse extends Response {
26
+ static {
27
+ this.status = 405;
28
+ }
29
+ constructor(...[body, init]) {
30
+ super(body, {
31
+ ...init,
32
+ status: _MethodNotAllowedResponse.status,
33
+ statusText: "Method Not Allowed"
34
+ });
35
+ }
36
+ };
37
+ var InternalServerErrorResponse = class _InternalServerErrorResponse extends Response {
38
+ static {
39
+ this.status = 500;
40
+ }
41
+ constructor(_, init) {
42
+ super(null, {
43
+ ...init,
44
+ status: _InternalServerErrorResponse.status
45
+ });
46
+ }
47
+ };
48
+ var NotModifiedResponse = class _NotModifiedResponse extends Response {
49
+ static {
50
+ this.status = 304;
51
+ }
52
+ constructor(...[_body, init]) {
53
+ super(null, {
54
+ ...init,
55
+ status: _NotModifiedResponse.status,
56
+ statusText: "Not Modified"
57
+ });
58
+ }
59
+ };
60
+ var MovedPermanentlyResponse = class _MovedPermanentlyResponse extends Response {
61
+ static {
62
+ this.status = 301;
63
+ }
64
+ constructor(location, init) {
65
+ super(null, {
66
+ ...init,
67
+ status: _MovedPermanentlyResponse.status,
68
+ statusText: "Moved Permanently",
69
+ headers: {
70
+ ...init?.headers,
71
+ Location: location
72
+ }
73
+ });
74
+ }
75
+ };
76
+ var FoundResponse = class _FoundResponse extends Response {
77
+ static {
78
+ this.status = 302;
79
+ }
80
+ constructor(location, init) {
81
+ super(null, {
82
+ ...init,
83
+ status: _FoundResponse.status,
84
+ statusText: "Found",
85
+ headers: {
86
+ ...init?.headers,
87
+ Location: location
88
+ }
89
+ });
90
+ }
91
+ };
92
+ var SeeOtherResponse = class _SeeOtherResponse extends Response {
93
+ static {
94
+ this.status = 303;
95
+ }
96
+ constructor(location, init) {
97
+ super(null, {
98
+ ...init,
99
+ status: _SeeOtherResponse.status,
100
+ statusText: "See Other",
101
+ headers: {
102
+ ...init?.headers,
103
+ Location: location
104
+ }
105
+ });
106
+ }
107
+ };
108
+ var TemporaryRedirectResponse = class _TemporaryRedirectResponse extends Response {
109
+ static {
110
+ this.status = 307;
111
+ }
112
+ constructor(location, init) {
113
+ super(null, {
114
+ ...init,
115
+ status: _TemporaryRedirectResponse.status,
116
+ statusText: "Temporary Redirect",
117
+ headers: {
118
+ ...init?.headers,
119
+ Location: location
120
+ }
121
+ });
122
+ }
123
+ };
124
+ var PermanentRedirectResponse = class _PermanentRedirectResponse extends Response {
125
+ static {
126
+ this.status = 308;
127
+ }
128
+ constructor(location, init) {
129
+ super(null, {
130
+ ...init,
131
+ status: _PermanentRedirectResponse.status,
132
+ statusText: "Permanent Redirect",
133
+ headers: {
134
+ ...init?.headers,
135
+ Location: location
136
+ }
137
+ });
138
+ }
139
+ };
140
+
141
+ // ../workers-shared/asset-worker/src/utils/rules-engine.ts
142
+ var ESCAPE_REGEX_CHARACTERS = /[-/\\^$*+?.()|[\]{}]/g;
143
+ var escapeRegex = (str) => {
144
+ return str.replace(ESCAPE_REGEX_CHARACTERS, "\\$&");
145
+ };
146
+ var HOST_PLACEHOLDER_REGEX = /(?<=^https:\\\/\\\/[^/]*?):([A-Za-z]\w*)(?=\\)/g;
147
+ var PLACEHOLDER_REGEX = /:([A-Za-z]\w*)/g;
148
+ var replacer = (str, replacements) => {
149
+ for (const [replacement, value] of Object.entries(replacements)) {
150
+ str = str.replaceAll(`:${replacement}`, value);
151
+ }
152
+ return str;
153
+ };
154
+ var generateRuleRegExp = (rule) => {
155
+ rule = rule.split("*").map(escapeRegex).join("(?<splat>.*)");
156
+ const host_matches = rule.matchAll(HOST_PLACEHOLDER_REGEX);
157
+ for (const host_match of host_matches) {
158
+ rule = rule.split(host_match[0]).join(`(?<${host_match[1]}>[^/.]+)`);
159
+ }
160
+ const path_matches = rule.matchAll(PLACEHOLDER_REGEX);
161
+ for (const path_match of path_matches) {
162
+ rule = rule.split(path_match[0]).join(`(?<${path_match[1]}>[^/]+)`);
163
+ }
164
+ rule = "^" + rule + "$";
165
+ return RegExp(rule);
166
+ };
167
+ var generateRulesMatcher = (rules, replacerFn = (match) => match) => {
168
+ if (!rules) {
169
+ return () => [];
170
+ }
171
+ const compiledRules = Object.entries(rules).map(([rule, match]) => {
172
+ const crossHost = rule.startsWith("https://");
173
+ try {
174
+ const regExp = generateRuleRegExp(rule);
175
+ return [{ crossHost, regExp }, match];
176
+ } catch {
177
+ }
178
+ }).filter((value) => value !== void 0);
179
+ return ({ request }) => {
180
+ const { pathname, hostname } = new URL(request.url);
181
+ return compiledRules.map(([{ crossHost, regExp }, match]) => {
182
+ const test = crossHost ? `https://${hostname}${pathname}` : pathname;
183
+ const result = regExp.exec(test);
184
+ if (result) {
185
+ return replacerFn(match, result.groups || {});
186
+ }
187
+ }).filter((value) => value !== void 0);
188
+ };
189
+ };
190
+
191
+ // asset-server/responses.ts
192
+ function mergeHeaders(base, extra) {
193
+ const baseHeaders = new Headers(base ?? {});
194
+ const extraHeaders = new Headers(extra ?? {});
195
+ return new Headers({
196
+ ...Object.fromEntries(baseHeaders.entries()),
197
+ ...Object.fromEntries(extraHeaders.entries())
198
+ });
199
+ }
200
+ function stripLeadingDoubleSlashes(location) {
201
+ return location.replace(/^(\/|%2F|%2f|%5C|%5c|%09|\s|\\)+(.*)/, "/$2");
202
+ }
203
+ var OkResponse2 = class extends Response {
204
+ constructor(...[body, init]) {
205
+ super(body, {
206
+ ...init,
207
+ status: 200,
208
+ statusText: "OK"
209
+ });
210
+ }
211
+ };
212
+ var MovedPermanentlyResponse2 = class extends Response {
213
+ constructor(location, init, {
214
+ preventLeadingDoubleSlash = true
215
+ } = {
216
+ preventLeadingDoubleSlash: true
217
+ }) {
218
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
219
+ super(`Redirecting to ${location}`, {
220
+ ...init,
221
+ status: 301,
222
+ statusText: "Moved Permanently",
223
+ headers: mergeHeaders(init?.headers, {
224
+ location
225
+ })
226
+ });
227
+ }
228
+ };
229
+ var FoundResponse2 = class extends Response {
230
+ constructor(location, init, {
231
+ preventLeadingDoubleSlash = true
232
+ } = {
233
+ preventLeadingDoubleSlash: true
234
+ }) {
235
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
236
+ super(`Redirecting to ${location}`, {
237
+ ...init,
238
+ status: 302,
239
+ statusText: "Found",
240
+ headers: mergeHeaders(init?.headers, {
241
+ location
242
+ })
243
+ });
244
+ }
245
+ };
246
+ var NotModifiedResponse2 = class extends Response {
247
+ constructor(...[_body, _init]) {
248
+ super(void 0, {
249
+ status: 304,
250
+ statusText: "Not Modified"
251
+ });
252
+ }
253
+ };
254
+ var PermanentRedirectResponse2 = class extends Response {
255
+ constructor(location, init, {
256
+ preventLeadingDoubleSlash = true
257
+ } = {
258
+ preventLeadingDoubleSlash: true
259
+ }) {
260
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
261
+ super(void 0, {
262
+ ...init,
263
+ status: 308,
264
+ statusText: "Permanent Redirect",
265
+ headers: mergeHeaders(init?.headers, {
266
+ location
267
+ })
268
+ });
269
+ }
270
+ };
271
+ var NotFoundResponse2 = class extends Response {
272
+ constructor(...[body, init]) {
273
+ super(body, {
274
+ ...init,
275
+ status: 404,
276
+ statusText: "Not Found"
277
+ });
278
+ }
279
+ };
280
+ var MethodNotAllowedResponse2 = class extends Response {
281
+ constructor(...[body, init]) {
282
+ super(body, {
283
+ ...init,
284
+ status: 405,
285
+ statusText: "Method Not Allowed"
286
+ });
287
+ }
288
+ };
289
+ var NotAcceptableResponse = class extends Response {
290
+ constructor(...[body, init]) {
291
+ super(body, {
292
+ ...init,
293
+ status: 406,
294
+ statusText: "Not Acceptable"
295
+ });
296
+ }
297
+ };
298
+ var InternalServerErrorResponse2 = class extends Response {
299
+ constructor(err, init) {
300
+ let body = void 0;
301
+ if (globalThis.DEBUG) {
302
+ body = `${err.message}
303
+
304
+ ${err.stack}`;
305
+ }
306
+ super(body, {
307
+ ...init,
308
+ status: 500,
309
+ statusText: "Internal Server Error"
310
+ });
311
+ }
312
+ };
313
+ var SeeOtherResponse2 = class extends Response {
314
+ constructor(location, init, {
315
+ preventLeadingDoubleSlash = true
316
+ } = {
317
+ preventLeadingDoubleSlash: true
318
+ }) {
319
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
320
+ super(`Redirecting to ${location}`, {
321
+ ...init,
322
+ status: 303,
323
+ statusText: "See Other",
324
+ headers: mergeHeaders(init?.headers, { location })
325
+ });
326
+ }
327
+ };
328
+ var TemporaryRedirectResponse2 = class extends Response {
329
+ constructor(location, init, {
330
+ preventLeadingDoubleSlash = true
331
+ } = {
332
+ preventLeadingDoubleSlash: true
333
+ }) {
334
+ location = preventLeadingDoubleSlash ? stripLeadingDoubleSlashes(location) : location;
335
+ super(`Redirecting to ${location}`, {
336
+ ...init,
337
+ status: 307,
338
+ statusText: "Temporary Redirect",
339
+ headers: mergeHeaders(init?.headers, { location })
340
+ });
341
+ }
342
+ };
343
+
344
+ // asset-server/handler.ts
345
+ var ASSET_PRESERVATION_CACHE = "assetPreservationCacheV2";
346
+ var CACHE_CONTROL_PRESERVATION = "public, s-maxage=604800";
347
+ var CACHE_PRESERVATION_WRITE_FREQUENCY = 86400;
348
+ var CACHE_CONTROL_BROWSER2 = "public, max-age=0, must-revalidate";
349
+ var REDIRECTS_VERSION2 = 1;
350
+ var HEADERS_VERSION2 = 2;
351
+ var HEADERS_VERSION_V1 = 1;
352
+ var ANALYTICS_VERSION = 1;
353
+ var ALLOWED_EARLY_HINT_LINK_ATTRIBUTES = ["rel", "as", "href"];
354
+ function normaliseHeaders(headers) {
355
+ if (headers.version === HEADERS_VERSION2) {
356
+ return headers.rules;
357
+ } else if (headers.version === HEADERS_VERSION_V1) {
358
+ return Object.keys(headers.rules).reduce(
359
+ (acc, key) => {
360
+ acc[key] = {
361
+ set: headers.rules[key]
362
+ };
363
+ return acc;
364
+ },
365
+ {}
366
+ );
367
+ } else {
368
+ return {};
369
+ }
370
+ }
371
+ function generateETagHeader(assetKey) {
372
+ const strongETag = `"${assetKey}"`;
373
+ const weakETag = `W/"${assetKey}"`;
374
+ return { strongETag, weakETag };
375
+ }
376
+ function checkIfNoneMatch(request, strongETag, weakETag) {
377
+ const ifNoneMatch = request.headers.get("if-none-match");
378
+ return ifNoneMatch === weakETag || ifNoneMatch === strongETag;
379
+ }
380
+ async function generateHandler({
381
+ request,
382
+ metadata,
383
+ xServerEnvHeader,
384
+ xDeploymentIdHeader,
385
+ xWebAnalyticsHeader,
386
+ logError,
387
+ setMetrics,
388
+ findAssetEntryForPath,
389
+ getAssetKey,
390
+ negotiateContent,
391
+ fetchAsset,
392
+ generateNotFoundResponse = async (notFoundRequest, notFoundFindAssetEntryForPath, notFoundServeAsset) => {
393
+ let assetEntry;
394
+ if (assetEntry = await notFoundFindAssetEntryForPath("/index.html")) {
395
+ return notFoundServeAsset(assetEntry, { preserve: false });
396
+ }
397
+ return new NotFoundResponse2();
398
+ },
399
+ attachAdditionalHeaders = () => {
400
+ },
401
+ caches,
402
+ waitUntil
403
+ }) {
404
+ const url = new URL(request.url);
405
+ const { protocol, host, search } = url;
406
+ let { pathname } = url;
407
+ const earlyHintsCache = metadata.deploymentId ? await caches?.open(`eh:${metadata.deploymentId}`) : void 0;
408
+ const headerRules = metadata.headers ? normaliseHeaders(metadata.headers) : {};
409
+ const staticRules = metadata.redirects?.version === REDIRECTS_VERSION2 ? metadata.redirects.staticRules || {} : {};
410
+ const staticRedirectsMatcher2 = () => {
411
+ const withHostMatch = staticRules[`https://${host}${pathname}`];
412
+ const withoutHostMatch = staticRules[pathname];
413
+ if (withHostMatch && withoutHostMatch) {
414
+ if (withHostMatch.lineNumber < withoutHostMatch.lineNumber) {
415
+ return withHostMatch;
416
+ } else {
417
+ return withoutHostMatch;
418
+ }
419
+ }
420
+ return withHostMatch || withoutHostMatch;
421
+ };
422
+ const generateRedirectsMatcher2 = () => generateRulesMatcher(
423
+ metadata.redirects?.version === REDIRECTS_VERSION2 ? metadata.redirects.rules : {},
424
+ ({ status, to }, replacements) => ({
425
+ status,
426
+ to: replacer(to, replacements)
427
+ })
428
+ );
429
+ let assetEntry;
430
+ async function generateResponse() {
431
+ const match = staticRedirectsMatcher2() || generateRedirectsMatcher2()({ request })[0];
432
+ if (match) {
433
+ if (match.status === 200) {
434
+ pathname = new URL(match.to, request.url).pathname;
435
+ } else {
436
+ const { status, to } = match;
437
+ const destination = new URL(to, request.url);
438
+ const location = destination.origin === new URL(request.url).origin ? `${destination.pathname}${destination.search || search}${destination.hash}` : `${destination.href.slice(0, destination.href.length - (destination.search.length + destination.hash.length))}${destination.search ? destination.search : search}${destination.hash}`;
439
+ switch (status) {
440
+ case 301:
441
+ return new MovedPermanentlyResponse2(location, void 0, {
442
+ preventLeadingDoubleSlash: false
443
+ });
444
+ case 303:
445
+ return new SeeOtherResponse2(location, void 0, {
446
+ preventLeadingDoubleSlash: false
447
+ });
448
+ case 307:
449
+ return new TemporaryRedirectResponse2(location, void 0, {
450
+ preventLeadingDoubleSlash: false
451
+ });
452
+ case 308:
453
+ return new PermanentRedirectResponse2(location, void 0, {
454
+ preventLeadingDoubleSlash: false
455
+ });
456
+ case 302:
457
+ default:
458
+ return new FoundResponse2(location, void 0, {
459
+ preventLeadingDoubleSlash: false
460
+ });
461
+ }
462
+ }
463
+ }
464
+ if (!request.method.match(/^(get|head)$/i)) {
465
+ return new MethodNotAllowedResponse2();
466
+ }
467
+ try {
468
+ pathname = globalThis.decodeURIComponent(pathname);
469
+ } catch {
470
+ }
471
+ if (pathname.endsWith("/")) {
472
+ if (assetEntry = await findAssetEntryForPath(`${pathname}index.html`)) {
473
+ return serveAsset(assetEntry);
474
+ } else if (pathname.endsWith("/index/")) {
475
+ return new PermanentRedirectResponse2(
476
+ `/${pathname.slice(1, -"index/".length)}${search}`
477
+ );
478
+ } else if (assetEntry = await findAssetEntryForPath(
479
+ `${pathname.replace(/\/$/, ".html")}`
480
+ )) {
481
+ return new PermanentRedirectResponse2(
482
+ `/${pathname.slice(1, -1)}${search}`
483
+ );
484
+ } else {
485
+ return notFound();
486
+ }
487
+ }
488
+ if (assetEntry = await findAssetEntryForPath(pathname)) {
489
+ if (pathname.endsWith(".html")) {
490
+ const extensionlessPath = pathname.slice(0, -".html".length);
491
+ if (extensionlessPath.endsWith("/index")) {
492
+ return new PermanentRedirectResponse2(
493
+ `${extensionlessPath.replace(/\/index$/, "/")}${search}`
494
+ );
495
+ } else if (await findAssetEntryForPath(extensionlessPath) || extensionlessPath === "/") {
496
+ return serveAsset(assetEntry);
497
+ } else {
498
+ return new PermanentRedirectResponse2(`${extensionlessPath}${search}`);
499
+ }
500
+ } else {
501
+ return serveAsset(assetEntry);
502
+ }
503
+ } else if (pathname.endsWith("/index")) {
504
+ return new PermanentRedirectResponse2(
505
+ `/${pathname.slice(1, -"index".length)}${search}`
506
+ );
507
+ } else if (assetEntry = await findAssetEntryForPath(`${pathname}.html`)) {
508
+ return serveAsset(assetEntry);
509
+ }
510
+ if (assetEntry = await findAssetEntryForPath(`${pathname}/index.html`)) {
511
+ return new PermanentRedirectResponse2(`${pathname}/${search}`);
512
+ } else {
513
+ return notFound();
514
+ }
515
+ }
516
+ function isNullBodyStatus(status) {
517
+ return [101, 204, 205, 304].includes(status);
518
+ }
519
+ async function attachHeaders(response) {
520
+ const existingHeaders = new Headers(response.headers);
521
+ const eTag = existingHeaders.get("eTag")?.match(/^"(.*)"$/)?.[1];
522
+ const extraHeaders = new Headers({
523
+ "access-control-allow-origin": "*",
524
+ "referrer-policy": "strict-origin-when-cross-origin",
525
+ ...existingHeaders.has("content-type") ? { "x-content-type-options": "nosniff" } : {}
526
+ });
527
+ const headers = new Headers({
528
+ // But we intentionally override existing headers
529
+ ...Object.fromEntries(existingHeaders.entries()),
530
+ ...Object.fromEntries(extraHeaders.entries())
531
+ });
532
+ if (earlyHintsCache && isHTMLContentType(response.headers.get("Content-Type")) && eTag) {
533
+ const preEarlyHintsHeaders = new Headers(headers);
534
+ const earlyHintsCacheKey = `${protocol}//${host}/${eTag}`;
535
+ const earlyHintsResponse = await earlyHintsCache.match(earlyHintsCacheKey);
536
+ if (earlyHintsResponse) {
537
+ const earlyHintsLinkHeader = earlyHintsResponse.headers.get("Link");
538
+ if (earlyHintsLinkHeader) {
539
+ headers.set("Link", earlyHintsLinkHeader);
540
+ if (setMetrics) {
541
+ setMetrics({ earlyHintsResult: "used-hit" });
542
+ }
543
+ } else {
544
+ if (setMetrics) {
545
+ setMetrics({ earlyHintsResult: "notused-hit" });
546
+ }
547
+ }
548
+ } else {
549
+ if (setMetrics) {
550
+ setMetrics({ earlyHintsResult: "notused-miss" });
551
+ }
552
+ const clonedResponse = response.clone();
553
+ if (waitUntil) {
554
+ waitUntil(
555
+ (async () => {
556
+ try {
557
+ const links = [];
558
+ const transformedResponse = new HTMLRewriter().on(
559
+ "link[rel~=preconnect],link[rel~=preload],link[rel~=modulepreload]",
560
+ {
561
+ element(element) {
562
+ for (const [attributeName] of element.attributes) {
563
+ if (!ALLOWED_EARLY_HINT_LINK_ATTRIBUTES.includes(
564
+ attributeName.toLowerCase()
565
+ )) {
566
+ return;
567
+ }
568
+ }
569
+ const href = element.getAttribute("href") || void 0;
570
+ const rel = element.getAttribute("rel") || void 0;
571
+ const as = element.getAttribute("as") || void 0;
572
+ if (href && !href.startsWith("data:") && rel) {
573
+ links.push({ href, rel, as });
574
+ }
575
+ }
576
+ }
577
+ ).transform(clonedResponse);
578
+ await transformedResponse.text();
579
+ links.forEach(({ href, rel, as }) => {
580
+ let link = `<${href}>; rel="${rel}"`;
581
+ if (as) {
582
+ link += `; as=${as}`;
583
+ }
584
+ preEarlyHintsHeaders.append("Link", link);
585
+ });
586
+ const linkHeader = preEarlyHintsHeaders.get("Link");
587
+ const earlyHintsHeaders = new Headers({
588
+ "Cache-Control": "max-age=2592000"
589
+ // 30 days
590
+ });
591
+ if (linkHeader) {
592
+ earlyHintsHeaders.append("Link", linkHeader);
593
+ }
594
+ await earlyHintsCache.put(
595
+ earlyHintsCacheKey,
596
+ new Response(null, { headers: earlyHintsHeaders })
597
+ );
598
+ } catch {
599
+ await earlyHintsCache.put(
600
+ earlyHintsCacheKey,
601
+ new Response(null, {
602
+ headers: {
603
+ "Cache-Control": "max-age=86400"
604
+ // 1 day
605
+ }
606
+ })
607
+ );
608
+ }
609
+ })()
610
+ );
611
+ }
612
+ }
613
+ } else {
614
+ if (setMetrics) {
615
+ setMetrics({ earlyHintsResult: "disabled" });
616
+ }
617
+ }
618
+ const headersMatcher = generateRulesMatcher(
619
+ headerRules,
620
+ ({ set = {}, unset = [] }, replacements) => {
621
+ const replacedSet = {};
622
+ Object.keys(set).forEach((key) => {
623
+ replacedSet[key] = replacer(set[key], replacements);
624
+ });
625
+ return {
626
+ set: replacedSet,
627
+ unset
628
+ };
629
+ }
630
+ );
631
+ const matches = headersMatcher({ request });
632
+ const setMap = /* @__PURE__ */ new Set();
633
+ matches.forEach(({ set = {}, unset = [] }) => {
634
+ unset.forEach((key) => {
635
+ headers.delete(key);
636
+ });
637
+ Object.keys(set).forEach((key) => {
638
+ if (setMap.has(key.toLowerCase())) {
639
+ headers.append(key, set[key]);
640
+ } else {
641
+ headers.set(key, set[key]);
642
+ setMap.add(key.toLowerCase());
643
+ }
644
+ });
645
+ });
646
+ return new Response(
647
+ isNullBodyStatus(response.status) ? null : response.body,
648
+ {
649
+ headers,
650
+ status: response.status,
651
+ statusText: response.statusText
652
+ }
653
+ );
654
+ }
655
+ const responseWithoutHeaders = await generateResponse();
656
+ if (responseWithoutHeaders.status >= 500) {
657
+ return responseWithoutHeaders;
658
+ }
659
+ const responseWithHeaders = await attachHeaders(responseWithoutHeaders);
660
+ if (responseWithHeaders.status === 404) {
661
+ if (responseWithHeaders.headers.has("cache-control")) {
662
+ responseWithHeaders.headers.delete("cache-control");
663
+ }
664
+ responseWithHeaders.headers.append("cache-control", "no-store");
665
+ }
666
+ return responseWithHeaders;
667
+ async function serveAsset(servingAssetEntry, options = { preserve: true }) {
668
+ let content;
669
+ try {
670
+ content = negotiateContent(request, servingAssetEntry);
671
+ } catch {
672
+ return new NotAcceptableResponse();
673
+ }
674
+ const assetKey = getAssetKey(servingAssetEntry, content);
675
+ const { strongETag, weakETag } = generateETagHeader(assetKey);
676
+ const isIfNoneMatch = checkIfNoneMatch(request, strongETag, weakETag);
677
+ if (isIfNoneMatch) {
678
+ return new NotModifiedResponse2();
679
+ }
680
+ try {
681
+ const asset = await fetchAsset(assetKey);
682
+ const headers = {
683
+ etag: strongETag,
684
+ "content-type": asset.contentType
685
+ };
686
+ let encodeBody = "automatic";
687
+ if (xServerEnvHeader) {
688
+ headers["x-server-env"] = xServerEnvHeader;
689
+ }
690
+ if (xDeploymentIdHeader && metadata.deploymentId) {
691
+ headers["x-deployment-id"] = metadata.deploymentId;
692
+ }
693
+ if (content.encoding) {
694
+ encodeBody = "manual";
695
+ headers["cache-control"] = "no-transform";
696
+ headers["content-encoding"] = content.encoding;
697
+ }
698
+ const response = new OkResponse2(
699
+ request.method === "HEAD" ? null : asset.body,
700
+ {
701
+ headers,
702
+ encodeBody
703
+ }
704
+ );
705
+ if (isCacheable(request)) {
706
+ response.headers.append("cache-control", CACHE_CONTROL_BROWSER2);
707
+ }
708
+ attachAdditionalHeaders(response, content, servingAssetEntry, asset);
709
+ if (isPreview(new URL(request.url))) {
710
+ response.headers.set("x-robots-tag", "noindex");
711
+ }
712
+ if (options.preserve && waitUntil && caches) {
713
+ waitUntil(
714
+ (async () => {
715
+ try {
716
+ const assetPreservationCache = await caches.open(
717
+ ASSET_PRESERVATION_CACHE
718
+ );
719
+ const match = await assetPreservationCache.match(request);
720
+ if (!match || assetKey !== await match.text() || isPreservationCacheResponseExpiring(match)) {
721
+ const preservedResponse = new Response(assetKey, response);
722
+ preservedResponse.headers.set(
723
+ "cache-control",
724
+ CACHE_CONTROL_PRESERVATION
725
+ );
726
+ preservedResponse.headers.set("x-robots-tag", "noindex");
727
+ await assetPreservationCache.put(
728
+ request.url,
729
+ preservedResponse
730
+ );
731
+ }
732
+ } catch (err) {
733
+ logError(err);
734
+ }
735
+ })()
736
+ );
737
+ }
738
+ if (isHTMLContentType(asset.contentType) && metadata.analytics?.version === ANALYTICS_VERSION) {
739
+ if (xWebAnalyticsHeader) {
740
+ response.headers.set("x-cf-pages-analytics", "1");
741
+ }
742
+ return new HTMLRewriter().on("body", {
743
+ element(e) {
744
+ e.append(
745
+ `<!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "${metadata.analytics?.token}"}'><\/script><!-- Cloudflare Pages Analytics -->`,
746
+ { html: true }
747
+ );
748
+ }
749
+ }).transform(response);
750
+ }
751
+ return response;
752
+ } catch (err) {
753
+ logError(err);
754
+ return new InternalServerErrorResponse2(err);
755
+ }
756
+ }
757
+ async function notFound() {
758
+ if (caches) {
759
+ try {
760
+ const assetPreservationCache = await caches.open(
761
+ ASSET_PRESERVATION_CACHE
762
+ );
763
+ const preservedResponse = await assetPreservationCache.match(
764
+ request.url
765
+ );
766
+ if (preservedResponse) {
767
+ if (setMetrics) {
768
+ setMetrics({ preservationCacheResult: "checked-hit" });
769
+ }
770
+ const assetKey = await preservedResponse.text();
771
+ if (isNullBodyStatus(preservedResponse.status)) {
772
+ return new Response(null, preservedResponse);
773
+ }
774
+ if (assetKey) {
775
+ const { strongETag, weakETag } = generateETagHeader(assetKey);
776
+ const isIfNoneMatch = checkIfNoneMatch(
777
+ request,
778
+ strongETag,
779
+ weakETag
780
+ );
781
+ if (isIfNoneMatch) {
782
+ if (setMetrics) {
783
+ setMetrics({ preservationCacheResult: "not-modified" });
784
+ }
785
+ return new NotModifiedResponse2();
786
+ }
787
+ const asset = await fetchAsset(assetKey);
788
+ if (asset) {
789
+ return new Response(asset.body, preservedResponse);
790
+ } else {
791
+ logError(
792
+ new Error(
793
+ `preservation cache contained assetKey that does not exist in storage: ${assetKey}`
794
+ )
795
+ );
796
+ }
797
+ } else {
798
+ logError(new Error(`cached response had no assetKey: ${assetKey}`));
799
+ }
800
+ } else {
801
+ if (setMetrics) {
802
+ setMetrics({ preservationCacheResult: "checked-miss" });
803
+ }
804
+ }
805
+ } catch (err) {
806
+ logError(err);
807
+ }
808
+ } else {
809
+ if (setMetrics) {
810
+ setMetrics({ preservationCacheResult: "disabled" });
811
+ }
812
+ }
813
+ let cwd = pathname;
814
+ while (cwd) {
815
+ cwd = cwd.slice(0, cwd.lastIndexOf("/"));
816
+ if (assetEntry = await findAssetEntryForPath(`${cwd}/404.html`)) {
817
+ let content;
818
+ try {
819
+ content = negotiateContent(request, assetEntry);
820
+ } catch {
821
+ return new NotAcceptableResponse();
822
+ }
823
+ const assetKey = getAssetKey(assetEntry, content);
824
+ try {
825
+ const { body, contentType } = await fetchAsset(assetKey);
826
+ const response = new NotFoundResponse2(body);
827
+ response.headers.set("content-type", contentType);
828
+ return response;
829
+ } catch (err) {
830
+ logError(err);
831
+ return new InternalServerErrorResponse2(err);
832
+ }
833
+ }
834
+ }
835
+ return await generateNotFoundResponse(
836
+ request,
837
+ findAssetEntryForPath,
838
+ serveAsset
839
+ );
840
+ }
841
+ }
842
+ function parseQualityWeightedList(list = "") {
843
+ const items = {};
844
+ list.replace(/\s/g, "").split(",").forEach((el) => {
845
+ const [item, weight] = el.split(";q=");
846
+ items[item] = weight ? parseFloat(weight) : 1;
847
+ });
848
+ return items;
849
+ }
850
+ function isCacheable(request) {
851
+ return !request.headers.has("authorization") && !request.headers.has("range");
852
+ }
853
+ function isPreview(url) {
854
+ if (url.hostname.endsWith(".pages.dev")) {
855
+ return url.hostname.split(".").length > 3 ? true : false;
856
+ }
857
+ return false;
858
+ }
859
+ function isPreservationCacheResponseExpiring(response) {
860
+ const ageHeader = response.headers.get("age");
861
+ if (!ageHeader) {
862
+ return false;
863
+ }
864
+ try {
865
+ const age = parseInt(ageHeader);
866
+ const jitter = Math.floor(Math.random() * 43200);
867
+ if (age > CACHE_PRESERVATION_WRITE_FREQUENCY + jitter) {
868
+ return true;
869
+ }
870
+ } catch {
871
+ return false;
872
+ }
873
+ return false;
874
+ }
875
+ function isHTMLContentType(contentType) {
876
+ return contentType?.toLowerCase().startsWith("text/html") || false;
877
+ }
878
+ export {
879
+ ANALYTICS_VERSION,
880
+ ASSET_PRESERVATION_CACHE,
881
+ CACHE_CONTROL_BROWSER2 as CACHE_CONTROL_BROWSER,
882
+ CACHE_PRESERVATION_WRITE_FREQUENCY,
883
+ HEADERS_VERSION2 as HEADERS_VERSION,
884
+ HEADERS_VERSION_V1,
885
+ REDIRECTS_VERSION2 as REDIRECTS_VERSION,
886
+ generateHandler,
887
+ isPreservationCacheResponseExpiring,
888
+ normaliseHeaders,
889
+ parseQualityWeightedList
890
+ };