@cloudflare/pages-shared 0.0.1 → 0.0.4
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.
- package/dist/asset-server/handler.js +395 -0
- package/dist/asset-server/metadata.js +0 -0
- package/dist/asset-server/patchUrl.js +15 -0
- package/dist/asset-server/responses.js +123 -0
- package/dist/asset-server/rulesEngine.js +44 -0
- package/dist/environment-polyfills/index.js +10 -0
- package/dist/environment-polyfills/miniflare.js +13 -0
- package/dist/environment-polyfills/types.js +1 -0
- package/dist/metadata-generator/createMetadataObject.js +1 -1
- package/package.json +10 -3
- package/src/asset-server/handler.ts +600 -0
- package/src/asset-server/metadata.ts +66 -0
- package/src/asset-server/patchUrl.ts +22 -0
- package/src/asset-server/responses.ts +152 -0
- package/src/asset-server/rulesEngine.ts +82 -0
- package/src/environment-polyfills/index.ts +14 -0
- package/src/environment-polyfills/miniflare.ts +14 -0
- package/src/environment-polyfills/types.ts +44 -0
- package/src/index.ts +1 -0
- package/src/metadata-generator/constants.ts +15 -0
- package/src/metadata-generator/createMetadataObject.ts +156 -0
- package/src/metadata-generator/parseHeaders.ts +168 -0
- package/src/metadata-generator/parseRedirects.ts +129 -0
- package/src/metadata-generator/types.ts +89 -0
- package/src/metadata-generator/validateURL.ts +57 -0
- package/tsconfig.json +1 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MAX_LINE_LENGTH,
|
|
3
|
+
MAX_DYNAMIC_REDIRECT_RULES,
|
|
4
|
+
MAX_STATIC_REDIRECT_RULES,
|
|
5
|
+
PERMITTED_STATUS_CODES,
|
|
6
|
+
SPLAT_REGEX,
|
|
7
|
+
PLACEHOLDER_REGEX,
|
|
8
|
+
} from "./constants";
|
|
9
|
+
import { validateUrl } from "./validateURL";
|
|
10
|
+
import type {
|
|
11
|
+
InvalidRedirectRule,
|
|
12
|
+
ParsedRedirects,
|
|
13
|
+
RedirectLine,
|
|
14
|
+
RedirectRule,
|
|
15
|
+
} from "./types";
|
|
16
|
+
|
|
17
|
+
export function parseRedirects(input: string): ParsedRedirects {
|
|
18
|
+
const lines = input.split("\n");
|
|
19
|
+
const rules: RedirectRule[] = [];
|
|
20
|
+
const seen_paths = new Set<string>();
|
|
21
|
+
const invalid: InvalidRedirectRule[] = [];
|
|
22
|
+
|
|
23
|
+
let staticRules = 0;
|
|
24
|
+
let dynamicRules = 0;
|
|
25
|
+
let canCreateStaticRule = true;
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < lines.length; i++) {
|
|
28
|
+
const line = lines[i].trim();
|
|
29
|
+
if (line.length === 0 || line.startsWith("#")) continue;
|
|
30
|
+
|
|
31
|
+
if (line.length > MAX_LINE_LENGTH) {
|
|
32
|
+
invalid.push({
|
|
33
|
+
message: `Ignoring line ${
|
|
34
|
+
i + 1
|
|
35
|
+
} as it exceeds the maximum allowed length of ${MAX_LINE_LENGTH}.`,
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const tokens = line.split(/\s+/);
|
|
41
|
+
|
|
42
|
+
if (tokens.length < 2 || tokens.length > 3) {
|
|
43
|
+
invalid.push({
|
|
44
|
+
line,
|
|
45
|
+
lineNumber: i + 1,
|
|
46
|
+
message: `Expected exactly 2 or 3 whitespace-separated tokens. Got ${tokens.length}.`,
|
|
47
|
+
});
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const [str_from, str_to, str_status = "302"] = tokens as RedirectLine;
|
|
52
|
+
|
|
53
|
+
const fromResult = validateUrl(str_from, true, false, false);
|
|
54
|
+
if (fromResult[0] === undefined) {
|
|
55
|
+
invalid.push({
|
|
56
|
+
line,
|
|
57
|
+
lineNumber: i + 1,
|
|
58
|
+
message: fromResult[1],
|
|
59
|
+
});
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const from = fromResult[0];
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
canCreateStaticRule &&
|
|
66
|
+
!from.match(SPLAT_REGEX) &&
|
|
67
|
+
!from.match(PLACEHOLDER_REGEX)
|
|
68
|
+
) {
|
|
69
|
+
staticRules += 1;
|
|
70
|
+
|
|
71
|
+
if (staticRules > MAX_STATIC_REDIRECT_RULES) {
|
|
72
|
+
invalid.push({
|
|
73
|
+
message: `Maximum number of static rules supported is ${MAX_STATIC_REDIRECT_RULES}. Skipping line.`,
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
dynamicRules += 1;
|
|
79
|
+
canCreateStaticRule = false;
|
|
80
|
+
|
|
81
|
+
if (dynamicRules > MAX_DYNAMIC_REDIRECT_RULES) {
|
|
82
|
+
invalid.push({
|
|
83
|
+
message: `Maximum number of dynamic rules supported is ${MAX_DYNAMIC_REDIRECT_RULES}. Skipping remaining ${
|
|
84
|
+
lines.length - i
|
|
85
|
+
} lines of file.`,
|
|
86
|
+
});
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const toResult = validateUrl(str_to, false, true, true);
|
|
92
|
+
if (toResult[0] === undefined) {
|
|
93
|
+
invalid.push({
|
|
94
|
+
line,
|
|
95
|
+
lineNumber: i + 1,
|
|
96
|
+
message: toResult[1],
|
|
97
|
+
});
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const to = toResult[0];
|
|
101
|
+
|
|
102
|
+
const status = Number(str_status);
|
|
103
|
+
if (isNaN(status) || !PERMITTED_STATUS_CODES.has(status)) {
|
|
104
|
+
invalid.push({
|
|
105
|
+
line,
|
|
106
|
+
lineNumber: i + 1,
|
|
107
|
+
message: `Valid status codes are 301, 302 (default), 303, 307, or 308. Got ${str_status}.`,
|
|
108
|
+
});
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (seen_paths.has(from)) {
|
|
113
|
+
invalid.push({
|
|
114
|
+
line,
|
|
115
|
+
lineNumber: i + 1,
|
|
116
|
+
message: `Ignoring duplicate rule for path ${from}.`,
|
|
117
|
+
});
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
seen_paths.add(from);
|
|
121
|
+
|
|
122
|
+
rules.push({ from, to, status, lineNumber: i + 1 });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
rules,
|
|
127
|
+
invalid,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* REDIRECT PARSING TYPES */
|
|
2
|
+
|
|
3
|
+
export type RedirectLine = [from: string, to: string, status?: number];
|
|
4
|
+
export type RedirectRule = {
|
|
5
|
+
from: string;
|
|
6
|
+
to: string;
|
|
7
|
+
status: number;
|
|
8
|
+
lineNumber: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type Headers = Record<string, string>;
|
|
12
|
+
export type HeadersRule = {
|
|
13
|
+
path: string;
|
|
14
|
+
headers: Headers;
|
|
15
|
+
unsetHeaders: string[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type InvalidRedirectRule = {
|
|
19
|
+
line?: string;
|
|
20
|
+
lineNumber?: number;
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type InvalidHeadersRule = {
|
|
25
|
+
line?: string;
|
|
26
|
+
lineNumber?: number;
|
|
27
|
+
message: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type ParsedRedirects = {
|
|
31
|
+
invalid: InvalidRedirectRule[];
|
|
32
|
+
rules: RedirectRule[];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** Parsed redirects and input file */
|
|
36
|
+
export type ParsedRedirectsWithFile = {
|
|
37
|
+
parsedRedirects?: ParsedRedirects;
|
|
38
|
+
file?: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type ParsedHeaders = {
|
|
42
|
+
invalid: InvalidHeadersRule[];
|
|
43
|
+
rules: HeadersRule[];
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Parsed headers and input file */
|
|
47
|
+
export type ParsedHeadersWithFile = {
|
|
48
|
+
parsedHeaders?: ParsedHeaders;
|
|
49
|
+
file?: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/* METADATA TYPES*/
|
|
53
|
+
|
|
54
|
+
export type MetadataRedirectEntry = {
|
|
55
|
+
status: number;
|
|
56
|
+
to: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type MetadataRedirects = {
|
|
60
|
+
[path: string]: MetadataRedirectEntry;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type MetadataHeaders = {
|
|
64
|
+
[path: string]: MetadataHeaderEntry;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type MetadataHeaderEntry = {
|
|
68
|
+
set?: Record<string, string>;
|
|
69
|
+
unset?: Array<string>;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type Metadata = {
|
|
73
|
+
redirects?: {
|
|
74
|
+
version: number;
|
|
75
|
+
staticRules: MetadataRedirects;
|
|
76
|
+
rules: MetadataRedirects;
|
|
77
|
+
};
|
|
78
|
+
headers?: {
|
|
79
|
+
version: number;
|
|
80
|
+
rules: MetadataHeaders;
|
|
81
|
+
};
|
|
82
|
+
analytics?: {
|
|
83
|
+
version: number;
|
|
84
|
+
token: string;
|
|
85
|
+
};
|
|
86
|
+
deploymentId?: string;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export type Logger = (message: string) => void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const extractPathname = (
|
|
2
|
+
path = "/",
|
|
3
|
+
includeSearch: boolean,
|
|
4
|
+
includeHash: boolean
|
|
5
|
+
): string => {
|
|
6
|
+
if (!path.startsWith("/")) path = `/${path}`;
|
|
7
|
+
const url = new URL(`//${path}`, "relative://");
|
|
8
|
+
return `${url.pathname}${includeSearch ? url.search : ""}${
|
|
9
|
+
includeHash ? url.hash : ""
|
|
10
|
+
}`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const URL_REGEX = /^https:\/\/+(?<host>[^/]+)\/?(?<path>.*)/;
|
|
14
|
+
const PATH_REGEX = /^\//;
|
|
15
|
+
|
|
16
|
+
export const validateUrl = (
|
|
17
|
+
token: string,
|
|
18
|
+
onlyRelative = false,
|
|
19
|
+
includeSearch = false,
|
|
20
|
+
includeHash = false
|
|
21
|
+
): [undefined, string] | [string, undefined] => {
|
|
22
|
+
const host = URL_REGEX.exec(token);
|
|
23
|
+
if (host && host.groups && host.groups.host) {
|
|
24
|
+
if (onlyRelative)
|
|
25
|
+
return [
|
|
26
|
+
undefined,
|
|
27
|
+
`Only relative URLs are allowed. Skipping absolute URL ${token}.`,
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
`https://${host.groups.host}${extractPathname(
|
|
32
|
+
host.groups.path,
|
|
33
|
+
includeSearch,
|
|
34
|
+
includeHash
|
|
35
|
+
)}`,
|
|
36
|
+
undefined,
|
|
37
|
+
];
|
|
38
|
+
} else {
|
|
39
|
+
if (!token.startsWith("/") && onlyRelative) token = `/${token}`;
|
|
40
|
+
|
|
41
|
+
const path = PATH_REGEX.exec(token);
|
|
42
|
+
if (path) {
|
|
43
|
+
try {
|
|
44
|
+
return [extractPathname(token, includeSearch, includeHash), undefined];
|
|
45
|
+
} catch {
|
|
46
|
+
return [undefined, `Error parsing URL segment ${token}. Skipping.`];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return [
|
|
52
|
+
undefined,
|
|
53
|
+
onlyRelative
|
|
54
|
+
? "URLs should begin with a forward-slash."
|
|
55
|
+
: 'URLs should either be relative (e.g. begin with a forward-slash), or use HTTPS (e.g. begin with "https://").',
|
|
56
|
+
];
|
|
57
|
+
};
|