@cloudflare/pages-shared 0.11.36 → 0.11.38

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.
@@ -133,7 +133,7 @@ export async function generateHandler<
133
133
  Asset extends { body: ReadableStream | null; contentType: string } = {
134
134
  body: ReadableStream | null;
135
135
  contentType: string;
136
- }
136
+ },
137
137
  >({
138
138
  request,
139
139
  metadata,
@@ -226,10 +226,10 @@ export async function generateHandler<
226
226
  destination.origin === new URL(request.url).origin
227
227
  ? `${destination.pathname}${destination.search || search}${
228
228
  destination.hash
229
- }`
229
+ }`
230
230
  : `${destination.href}${destination.search ? "" : search}${
231
231
  destination.hash
232
- }`;
232
+ }`;
233
233
  switch (status) {
234
234
  case 301:
235
235
  return new MovedPermanentlyResponse(location, undefined, {
@@ -350,19 +350,24 @@ export async function generateHandler<
350
350
  // "Early Hints cache entries are keyed by request URI and ignore query strings."
351
351
  // https://developers.cloudflare.com/cache/about/early-hints/
352
352
  const earlyHintsCacheKey = `${protocol}//${host}${pathname}`;
353
- const earlyHintsResponse = await earlyHintsCache.match(
354
- earlyHintsCacheKey
355
- );
353
+ const earlyHintsResponse =
354
+ await earlyHintsCache.match(earlyHintsCacheKey);
356
355
  if (earlyHintsResponse) {
357
356
  const earlyHintsLinkHeader = earlyHintsResponse.headers.get("Link");
358
357
  if (earlyHintsLinkHeader) {
359
358
  headers.set("Link", earlyHintsLinkHeader);
360
- if (setMetrics) setMetrics({ earlyHintsResult: "used-hit" });
359
+ if (setMetrics) {
360
+ setMetrics({ earlyHintsResult: "used-hit" });
361
+ }
361
362
  } else {
362
- if (setMetrics) setMetrics({ earlyHintsResult: "notused-hit" });
363
+ if (setMetrics) {
364
+ setMetrics({ earlyHintsResult: "notused-hit" });
365
+ }
363
366
  }
364
367
  } else {
365
- if (setMetrics) setMetrics({ earlyHintsResult: "notused-miss" });
368
+ if (setMetrics) {
369
+ setMetrics({ earlyHintsResult: "notused-miss" });
370
+ }
366
371
 
367
372
  const clonedResponse = response.clone();
368
373
 
@@ -373,26 +378,29 @@ export async function generateHandler<
373
378
  const links: { href: string; rel: string; as?: string }[] = [];
374
379
 
375
380
  const transformedResponse = new HTMLRewriter()
376
- .on("link[rel~=preconnect],link[rel~=preload]", {
377
- element(element) {
378
- for (const [attributeName] of element.attributes) {
379
- if (
380
- !ALLOWED_EARLY_HINT_LINK_ATTRIBUTES.includes(
381
- attributeName.toLowerCase()
382
- )
383
- ) {
384
- return;
381
+ .on(
382
+ "link[rel~=preconnect],link[rel~=preload],link[rel~=modulepreload]",
383
+ {
384
+ element(element) {
385
+ for (const [attributeName] of element.attributes) {
386
+ if (
387
+ !ALLOWED_EARLY_HINT_LINK_ATTRIBUTES.includes(
388
+ attributeName.toLowerCase()
389
+ )
390
+ ) {
391
+ return;
392
+ }
393
+ }
394
+
395
+ const href = element.getAttribute("href") || undefined;
396
+ const rel = element.getAttribute("rel") || undefined;
397
+ const as = element.getAttribute("as") || undefined;
398
+ if (href && !href.startsWith("data:") && rel) {
399
+ links.push({ href, rel, as });
385
400
  }
386
- }
387
-
388
- const href = element.getAttribute("href") || undefined;
389
- const rel = element.getAttribute("rel") || undefined;
390
- const as = element.getAttribute("as") || undefined;
391
- if (href && !href.startsWith("data:") && rel) {
392
- links.push({ href, rel, as });
393
- }
394
- },
395
- })
401
+ },
402
+ }
403
+ )
396
404
  .transform(clonedResponse);
397
405
 
398
406
  // Needed to actually execute the HTMLRewriter handlers
@@ -429,7 +437,9 @@ export async function generateHandler<
429
437
  }
430
438
  }
431
439
  } else {
432
- if (setMetrics) setMetrics({ earlyHintsResult: "disabled" });
440
+ if (setMetrics) {
441
+ setMetrics({ earlyHintsResult: "disabled" });
442
+ }
433
443
  }
434
444
 
435
445
  // Iterate through rules and find rules that match the path
@@ -482,7 +492,19 @@ export async function generateHandler<
482
492
  if (responseWithoutHeaders.status >= 500) {
483
493
  return responseWithoutHeaders;
484
494
  }
485
- return await attachHeaders(responseWithoutHeaders);
495
+
496
+ const responseWithHeaders = await attachHeaders(responseWithoutHeaders);
497
+ if (responseWithHeaders.status === 404) {
498
+ // Remove any user-controlled cache-control headers
499
+ // This is to prevent the footgun of potentionally caching this 404 for a long time
500
+ if (responseWithHeaders.headers.has("cache-control")) {
501
+ responseWithHeaders.headers.delete("cache-control");
502
+ }
503
+ // Add cache-control: no-store to prevent this from being cached on the responding zones.
504
+ responseWithHeaders.headers.append("cache-control", "no-store");
505
+ }
506
+
507
+ return responseWithHeaders;
486
508
 
487
509
  async function serveAsset(
488
510
  servingAssetEntry: AssetEntry,
@@ -675,7 +697,9 @@ export async function generateHandler<
675
697
  logError(err as Error);
676
698
  }
677
699
  } else {
678
- if (setMetrics) setMetrics({ preservationCacheResult: "disabled" });
700
+ if (setMetrics) {
701
+ setMetrics({ preservationCacheResult: "disabled" });
702
+ }
679
703
  }
680
704
 
681
705
  // Traverse upwards from the current path looking for a custom 404 page
@@ -748,13 +772,17 @@ export function isPreservationCacheResponseExpiring(
748
772
  response: Response
749
773
  ): boolean {
750
774
  const ageHeader = response.headers.get("age");
751
- if (!ageHeader) return false;
775
+ if (!ageHeader) {
776
+ return false;
777
+ }
752
778
  try {
753
779
  const age = parseInt(ageHeader);
754
780
  // Add up to 12 hours of jitter to help prevent a
755
781
  // thundering heard when a lot of assets expire at once.
756
782
  const jitter = Math.floor(Math.random() * 43_200);
757
- if (age > CACHE_PRESERVATION_WRITE_FREQUENCY + jitter) return true;
783
+ if (age > CACHE_PRESERVATION_WRITE_FREQUENCY + jitter) {
784
+ return true;
785
+ }
758
786
  } catch {
759
787
  return false;
760
788
  }
@@ -28,7 +28,9 @@ export const generateRulesMatcher = <T>(
28
28
  rules?: Record<string, T>,
29
29
  replacerFn: (match: T, replacements: Replacements) => T = (match) => match
30
30
  ) => {
31
- if (!rules) return () => [];
31
+ if (!rules) {
32
+ return () => [];
33
+ }
32
34
 
33
35
  const compiledRules = Object.entries(rules)
34
36
  .map(([rule, match]) => {
@@ -64,7 +66,7 @@ export const generateRulesMatcher = <T>(
64
66
  })
65
67
  .filter((value) => value !== undefined) as [
66
68
  { crossHost: boolean; regExp: RegExp },
67
- T
69
+ T,
68
70
  ][];
69
71
 
70
72
  return ({ request }: { request: Request }) => {
@@ -54,7 +54,9 @@ function constructRedirects({
54
54
  redirects?: ParsedRedirects;
55
55
  logger: Logger;
56
56
  }): Metadata {
57
- if (!redirects) return {};
57
+ if (!redirects) {
58
+ return {};
59
+ }
58
60
 
59
61
  const num_valid = redirects.rules.length;
60
62
  const num_invalid = redirects.invalid.length;
@@ -117,7 +119,9 @@ function constructHeaders({
117
119
  headers?: ParsedHeaders;
118
120
  logger: Logger;
119
121
  }): Metadata {
120
- if (!headers) return {};
122
+ if (!headers) {
123
+ return {};
124
+ }
121
125
 
122
126
  const num_valid = headers.rules.length;
123
127
  const num_invalid = headers.invalid.length;
@@ -167,7 +171,9 @@ function constructWebAnalytics({
167
171
  webAnalyticsToken?: string;
168
172
  logger: Logger;
169
173
  }) {
170
- if (!webAnalyticsToken) return {};
174
+ if (!webAnalyticsToken) {
175
+ return {};
176
+ }
171
177
 
172
178
  return {
173
179
  analytics: {
@@ -21,7 +21,9 @@ export function parseHeaders(input: string): ParsedHeaders {
21
21
 
22
22
  for (let i = 0; i < lines.length; i++) {
23
23
  const line = lines[i].trim();
24
- if (line.length === 0 || line.startsWith("#")) continue;
24
+ if (line.length === 0 || line.startsWith("#")) {
25
+ continue;
26
+ }
25
27
 
26
28
  if (line.length > MAX_LINE_LENGTH) {
27
29
  invalid.push({
@@ -26,7 +26,9 @@ export function parseRedirects(input: string): ParsedRedirects {
26
26
 
27
27
  for (let i = 0; i < lines.length; i++) {
28
28
  const line = lines[i].trim();
29
- if (line.length === 0 || line.startsWith("#")) continue;
29
+ if (line.length === 0 || line.startsWith("#")) {
30
+ continue;
31
+ }
30
32
 
31
33
  if (line.length > MAX_LINE_LENGTH) {
32
34
  invalid.push({
@@ -3,7 +3,9 @@ export const extractPathname = (
3
3
  includeSearch: boolean,
4
4
  includeHash: boolean
5
5
  ): string => {
6
- if (!path.startsWith("/")) path = `/${path}`;
6
+ if (!path.startsWith("/")) {
7
+ path = `/${path}`;
8
+ }
7
9
  const url = new URL(`//${path}`, "relative://");
8
10
  return `${url.pathname}${includeSearch ? url.search : ""}${
9
11
  includeHash ? url.hash : ""
@@ -23,11 +25,12 @@ export const validateUrl = (
23
25
  ): [undefined, string] | [string, undefined] => {
24
26
  const host = URL_REGEX.exec(token);
25
27
  if (host && host.groups && host.groups.host) {
26
- if (onlyRelative)
28
+ if (onlyRelative) {
27
29
  return [
28
30
  undefined,
29
31
  `Only relative URLs are allowed. Skipping absolute URL ${token}.`,
30
32
  ];
33
+ }
31
34
 
32
35
  if (disallowPorts && host.groups.host.match(HOST_WITH_PORT_REGEX)) {
33
36
  return [
@@ -45,7 +48,9 @@ export const validateUrl = (
45
48
  undefined,
46
49
  ];
47
50
  } else {
48
- if (!token.startsWith("/") && onlyRelative) token = `/${token}`;
51
+ if (!token.startsWith("/") && onlyRelative) {
52
+ token = `/${token}`;
53
+ }
49
54
 
50
55
  const path = PATH_REGEX.exec(token);
51
56
  if (path) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/pages-shared",
3
- "version": "0.11.36",
3
+ "version": "0.11.38",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/cloudflare/workers-sdk.git",
@@ -30,6 +30,7 @@
30
30
  },
31
31
  "scripts": {
32
32
  "check:type": "tsc",
33
+ "check:lint": "eslint .",
33
34
  "test": "vitest run",
34
35
  "test:ci": "vitest run"
35
36
  }