@cloudflare/pages-shared 0.0.0-ship-js
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/README.md +5 -0
- package/asset-server/handler.ts +625 -0
- package/asset-server/metadata.ts +67 -0
- package/asset-server/patchUrl.ts +22 -0
- package/asset-server/responses.ts +196 -0
- package/asset-server/rulesEngine.ts +82 -0
- package/dist/__tests__/asset-server/handler.test.d.ts +2 -0
- package/dist/__tests__/asset-server/handler.test.d.ts.map +1 -0
- package/dist/__tests__/asset-server/handler.test.js +430 -0
- package/dist/__tests__/asset-server/responses.test.d.ts +2 -0
- package/dist/__tests__/asset-server/responses.test.d.ts.map +1 -0
- package/dist/__tests__/asset-server/responses.test.js +22 -0
- package/dist/__tests__/asset-server/rulesEngine.test.d.ts +2 -0
- package/dist/__tests__/asset-server/rulesEngine.test.d.ts.map +1 -0
- package/dist/__tests__/asset-server/rulesEngine.test.js +70 -0
- package/dist/__tests__/jest.setup.d.ts +2 -0
- package/dist/__tests__/jest.setup.d.ts.map +1 -0
- package/dist/__tests__/jest.setup.js +7 -0
- package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/createMetadataObject.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/createMetadataObject.test.js +293 -0
- package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseHeaders.invalid.test.js +194 -0
- package/dist/__tests__/metadata-generator/parseHeaders.valid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseHeaders.valid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseHeaders.valid.test.js +132 -0
- package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseRedirects.invalid.test.js +243 -0
- package/dist/__tests__/metadata-generator/parseRedirects.valid.test.d.ts +2 -0
- package/dist/__tests__/metadata-generator/parseRedirects.valid.test.d.ts.map +1 -0
- package/dist/__tests__/metadata-generator/parseRedirects.valid.test.js +88 -0
- package/dist/asset-server/handler.d.ts +44 -0
- package/dist/asset-server/handler.d.ts.map +1 -0
- package/dist/asset-server/handler.js +420 -0
- package/dist/asset-server/metadata.d.ts +52 -0
- package/dist/asset-server/metadata.d.ts.map +1 -0
- package/dist/asset-server/metadata.js +3 -0
- package/dist/asset-server/patchUrl.d.ts +2 -0
- package/dist/asset-server/patchUrl.d.ts.map +1 -0
- package/dist/asset-server/patchUrl.js +19 -0
- package/dist/asset-server/responses.d.ts +45 -0
- package/dist/asset-server/responses.d.ts.map +1 -0
- package/dist/asset-server/responses.js +165 -0
- package/dist/asset-server/rulesEngine.d.ts +7 -0
- package/dist/asset-server/rulesEngine.d.ts.map +1 -0
- package/dist/asset-server/rulesEngine.js +68 -0
- package/dist/environment-polyfills/index.d.ts +3 -0
- package/dist/environment-polyfills/index.d.ts.map +1 -0
- package/dist/environment-polyfills/index.js +14 -0
- package/dist/environment-polyfills/miniflare-tre.d.ts +3 -0
- package/dist/environment-polyfills/miniflare-tre.d.ts.map +1 -0
- package/dist/environment-polyfills/miniflare-tre.js +35 -0
- package/dist/environment-polyfills/miniflare.d.ts +3 -0
- package/dist/environment-polyfills/miniflare.d.ts.map +1 -0
- package/dist/environment-polyfills/miniflare.js +35 -0
- package/dist/environment-polyfills/types.d.ts +34 -0
- package/dist/environment-polyfills/types.d.ts.map +1 -0
- package/dist/environment-polyfills/types.js +5 -0
- package/dist/metadata-generator/constants.d.ts +14 -0
- package/dist/metadata-generator/constants.d.ts.map +1 -0
- package/dist/metadata-generator/constants.js +16 -0
- package/dist/metadata-generator/createMetadataObject.d.ts +10 -0
- package/dist/metadata-generator/createMetadataObject.d.ts.map +1 -0
- package/dist/metadata-generator/createMetadataObject.js +105 -0
- package/dist/metadata-generator/parseHeaders.d.ts +3 -0
- package/dist/metadata-generator/parseHeaders.d.ts.map +1 -0
- package/dist/metadata-generator/parseHeaders.js +146 -0
- package/dist/metadata-generator/parseRedirects.d.ts +3 -0
- package/dist/metadata-generator/parseRedirects.d.ts.map +1 -0
- package/dist/metadata-generator/parseRedirects.js +100 -0
- package/dist/metadata-generator/types.d.ts +74 -0
- package/dist/metadata-generator/types.d.ts.map +1 -0
- package/dist/metadata-generator/types.js +3 -0
- package/dist/metadata-generator/validateURL.d.ts +3 -0
- package/dist/metadata-generator/validateURL.d.ts.map +1 -0
- package/dist/metadata-generator/validateURL.js +46 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/environment-polyfills/index.ts +14 -0
- package/environment-polyfills/miniflare-tre.ts +12 -0
- package/environment-polyfills/miniflare.ts +12 -0
- package/environment-polyfills/types.ts +42 -0
- package/metadata-generator/constants.ts +15 -0
- package/metadata-generator/createMetadataObject.ts +164 -0
- package/metadata-generator/parseHeaders.ts +168 -0
- package/metadata-generator/parseRedirects.ts +129 -0
- package/metadata-generator/types.ts +90 -0
- package/metadata-generator/validateURL.ts +57 -0
- package/package.json +63 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createMetadataObject_1 = require("../..//metadata-generator/createMetadataObject");
|
|
4
|
+
const homeRedirectRule = {
|
|
5
|
+
from: "/home",
|
|
6
|
+
to: "/",
|
|
7
|
+
status: 302,
|
|
8
|
+
lineNumber: 1,
|
|
9
|
+
};
|
|
10
|
+
const splatRedirectRule = {
|
|
11
|
+
from: "/blog/*",
|
|
12
|
+
to: "/blog/:splat",
|
|
13
|
+
status: 302,
|
|
14
|
+
lineNumber: 2,
|
|
15
|
+
};
|
|
16
|
+
const placeholderRedirectRule = {
|
|
17
|
+
from: "/blog/:year/:month/:date/:slug",
|
|
18
|
+
to: "/news/:year/:month/:date/:slug",
|
|
19
|
+
status: 302,
|
|
20
|
+
lineNumber: 3,
|
|
21
|
+
};
|
|
22
|
+
const fooBarRedirectRule = {
|
|
23
|
+
from: "/foo",
|
|
24
|
+
to: "/bar",
|
|
25
|
+
status: 302,
|
|
26
|
+
lineNumber: 4,
|
|
27
|
+
};
|
|
28
|
+
const homeHeadersRule = {
|
|
29
|
+
path: "/home",
|
|
30
|
+
headers: {
|
|
31
|
+
"Access-Control-Allow-Origin": "*",
|
|
32
|
+
},
|
|
33
|
+
unsetHeaders: [],
|
|
34
|
+
};
|
|
35
|
+
test("createMetadataObject should return no redirects or headers entry for no valid rules", () => {
|
|
36
|
+
{
|
|
37
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
38
|
+
redirects: {
|
|
39
|
+
rules: [],
|
|
40
|
+
invalid: [],
|
|
41
|
+
},
|
|
42
|
+
headers: {
|
|
43
|
+
rules: [],
|
|
44
|
+
invalid: [],
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
expect(metadata.redirects).toEqual(undefined);
|
|
48
|
+
expect(metadata.headers).toEqual(undefined);
|
|
49
|
+
}
|
|
50
|
+
{
|
|
51
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({});
|
|
52
|
+
expect(metadata.redirects).toEqual(undefined);
|
|
53
|
+
expect(metadata.headers).toEqual(undefined);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
test("createMetadataObject should add Version", () => {
|
|
57
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
58
|
+
redirects: {
|
|
59
|
+
rules: [homeRedirectRule],
|
|
60
|
+
invalid: [],
|
|
61
|
+
},
|
|
62
|
+
headers: {
|
|
63
|
+
rules: [homeHeadersRule],
|
|
64
|
+
invalid: [],
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
expect(metadata.redirects?.version).toEqual(1);
|
|
68
|
+
expect(metadata.headers?.version).toEqual(2);
|
|
69
|
+
});
|
|
70
|
+
test("createMetadataObject should construct mapping of from to to/status", () => {
|
|
71
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
72
|
+
redirects: {
|
|
73
|
+
rules: [
|
|
74
|
+
homeRedirectRule,
|
|
75
|
+
splatRedirectRule,
|
|
76
|
+
placeholderRedirectRule,
|
|
77
|
+
fooBarRedirectRule,
|
|
78
|
+
],
|
|
79
|
+
invalid: [],
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
expect(metadata.redirects).toEqual({
|
|
83
|
+
version: 1,
|
|
84
|
+
staticRules: {
|
|
85
|
+
"/home": { status: 302, to: "/", lineNumber: 1 },
|
|
86
|
+
},
|
|
87
|
+
rules: {
|
|
88
|
+
"/blog/*": {
|
|
89
|
+
to: "/blog/:splat",
|
|
90
|
+
status: 302,
|
|
91
|
+
},
|
|
92
|
+
"/blog/:year/:month/:date/:slug": {
|
|
93
|
+
status: 302,
|
|
94
|
+
to: "/news/:year/:month/:date/:slug",
|
|
95
|
+
},
|
|
96
|
+
"/foo": {
|
|
97
|
+
status: 302,
|
|
98
|
+
to: "/bar",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
test("createMetadataObject should construct mapping of path to headers", () => {
|
|
104
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
105
|
+
headers: {
|
|
106
|
+
rules: [homeHeadersRule],
|
|
107
|
+
invalid: [],
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
expect(metadata.headers).toEqual({
|
|
111
|
+
version: 2,
|
|
112
|
+
rules: {
|
|
113
|
+
"/home": {
|
|
114
|
+
set: { "Access-Control-Allow-Origin": "*" },
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
test("createMetadataObject should return no analytics entry for null", () => {
|
|
120
|
+
{
|
|
121
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({});
|
|
122
|
+
expect(metadata.analytics).toEqual(undefined);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
test("createMetadataObject should pass through the token", () => {
|
|
126
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
127
|
+
webAnalyticsToken: "secret_token_1234",
|
|
128
|
+
});
|
|
129
|
+
expect(metadata.analytics).toEqual({
|
|
130
|
+
version: 1,
|
|
131
|
+
token: "secret_token_1234",
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
test("createMetadataObject should parse a realistic result", () => {
|
|
135
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
136
|
+
redirects: {
|
|
137
|
+
invalid: [
|
|
138
|
+
{
|
|
139
|
+
line: `/some page /somewhere else`,
|
|
140
|
+
message: "Expected exactly 2 or 3 whitespace-separated tokens. Got 4.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
line: `https://yeah.com https://nah.com`,
|
|
144
|
+
message: "Only relative URLs are allowed. Skipping absolute URL https://yeah.com.",
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
rules: [
|
|
148
|
+
{
|
|
149
|
+
from: "/some%20page",
|
|
150
|
+
status: 302,
|
|
151
|
+
to: "/somewhere%20else",
|
|
152
|
+
lineNumber: 1,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
from: "/://so;%60me",
|
|
156
|
+
status: 302,
|
|
157
|
+
to: "/nons:/&@%+~%7B%7Dense",
|
|
158
|
+
lineNumber: 2,
|
|
159
|
+
},
|
|
160
|
+
{ from: "/nah", status: 302, to: "https://yeah.com/", lineNumber: 3 },
|
|
161
|
+
{
|
|
162
|
+
from: "/yeah.com",
|
|
163
|
+
status: 302,
|
|
164
|
+
to: "https://nah.com/",
|
|
165
|
+
lineNumber: 4,
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
headers: {
|
|
170
|
+
invalid: [
|
|
171
|
+
{
|
|
172
|
+
line: "HEADERSTODO",
|
|
173
|
+
message: "HEADERSTODO",
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
rules: [
|
|
177
|
+
{
|
|
178
|
+
path: "/static/*",
|
|
179
|
+
headers: { "Access-Control-Allow-Origin": "*" },
|
|
180
|
+
unsetHeaders: [],
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
path: "/logout",
|
|
184
|
+
headers: {
|
|
185
|
+
"Set-Cookie": "session=; Expires=Thu, 01 Jan 1970 00:00:00 GMT",
|
|
186
|
+
"x-content-type-options": "nosniff",
|
|
187
|
+
"x-frame-options": "DENY",
|
|
188
|
+
},
|
|
189
|
+
unsetHeaders: [],
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
path: "https://my.pages.dev/*",
|
|
193
|
+
headers: { "X-Robots-Tag": "none" },
|
|
194
|
+
unsetHeaders: [],
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
webAnalyticsToken: "secret_token_1234",
|
|
199
|
+
deploymentId: "some-deployment-123",
|
|
200
|
+
});
|
|
201
|
+
expect(metadata).toEqual({
|
|
202
|
+
redirects: {
|
|
203
|
+
version: 1,
|
|
204
|
+
rules: {},
|
|
205
|
+
staticRules: {
|
|
206
|
+
"/some%20page": { status: 302, to: "/somewhere%20else", lineNumber: 1 },
|
|
207
|
+
"/://so;%60me": {
|
|
208
|
+
status: 302,
|
|
209
|
+
to: "/nons:/&@%+~%7B%7Dense",
|
|
210
|
+
lineNumber: 2,
|
|
211
|
+
},
|
|
212
|
+
"/nah": { status: 302, to: "https://yeah.com/", lineNumber: 3 },
|
|
213
|
+
"/yeah.com": { status: 302, to: "https://nah.com/", lineNumber: 4 },
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
headers: {
|
|
217
|
+
version: 2,
|
|
218
|
+
rules: {
|
|
219
|
+
"/static/*": {
|
|
220
|
+
set: {
|
|
221
|
+
"Access-Control-Allow-Origin": "*",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
"/logout": {
|
|
225
|
+
set: {
|
|
226
|
+
"Set-Cookie": "session=; Expires=Thu, 01 Jan 1970 00:00:00 GMT",
|
|
227
|
+
"x-content-type-options": "nosniff",
|
|
228
|
+
"x-frame-options": "DENY",
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
"https://my.pages.dev/*": {
|
|
232
|
+
set: { "X-Robots-Tag": "none" },
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
analytics: {
|
|
237
|
+
version: 1,
|
|
238
|
+
token: "secret_token_1234",
|
|
239
|
+
},
|
|
240
|
+
deploymentId: "some-deployment-123",
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
test("createMetadataObject should include unset", () => {
|
|
244
|
+
const metadata = (0, createMetadataObject_1.createMetadataObject)({
|
|
245
|
+
headers: {
|
|
246
|
+
invalid: [],
|
|
247
|
+
rules: [
|
|
248
|
+
{
|
|
249
|
+
path: "/*",
|
|
250
|
+
headers: { "x-custom-header": "value" },
|
|
251
|
+
unsetHeaders: [],
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
path: "/foo/*",
|
|
255
|
+
headers: {},
|
|
256
|
+
unsetHeaders: ["x-custom-header"],
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
path: "/foo/bar/*",
|
|
260
|
+
headers: { "x-custom-header": "newvalue" },
|
|
261
|
+
unsetHeaders: [],
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
},
|
|
265
|
+
webAnalyticsToken: "secret_token_1234",
|
|
266
|
+
deploymentId: "some-deployment-id",
|
|
267
|
+
});
|
|
268
|
+
expect(metadata).toEqual({
|
|
269
|
+
analytics: {
|
|
270
|
+
token: "secret_token_1234",
|
|
271
|
+
version: 1,
|
|
272
|
+
},
|
|
273
|
+
headers: {
|
|
274
|
+
version: 2,
|
|
275
|
+
rules: {
|
|
276
|
+
"/*": {
|
|
277
|
+
set: {
|
|
278
|
+
"x-custom-header": "value",
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
"/foo/*": {
|
|
282
|
+
unset: ["x-custom-header"],
|
|
283
|
+
},
|
|
284
|
+
"/foo/bar/*": {
|
|
285
|
+
set: {
|
|
286
|
+
"x-custom-header": "newvalue",
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
deploymentId: "some-deployment-id",
|
|
292
|
+
});
|
|
293
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseHeaders.invalid.test.d.ts","sourceRoot":"","sources":["../../../__tests__/metadata-generator/parseHeaders.invalid.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const parseHeaders_1 = require("../..//metadata-generator/parseHeaders");
|
|
4
|
+
test("parseHeaders should reject malformed initial lines", () => {
|
|
5
|
+
const input = `
|
|
6
|
+
# A single token before a path
|
|
7
|
+
c
|
|
8
|
+
# A header before a path
|
|
9
|
+
Access-Control-Allow-Origin: *
|
|
10
|
+
`;
|
|
11
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
12
|
+
expect(result).toEqual({
|
|
13
|
+
rules: [],
|
|
14
|
+
invalid: [
|
|
15
|
+
{
|
|
16
|
+
line: "c",
|
|
17
|
+
lineNumber: 3,
|
|
18
|
+
message: "Expected a path beginning with at least one forward-slash",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
line: "Access-Control-Allow-Origin: *",
|
|
22
|
+
lineNumber: 5,
|
|
23
|
+
message: "Path should come before header (access-control-allow-origin: *)",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
test("parseHeaders should reject invalid headers", () => {
|
|
29
|
+
const input = `
|
|
30
|
+
# Valid header sails through
|
|
31
|
+
/a
|
|
32
|
+
Name: Value
|
|
33
|
+
#
|
|
34
|
+
/b
|
|
35
|
+
I'm invalid!
|
|
36
|
+
!x-content-type
|
|
37
|
+
But: I'm okay!
|
|
38
|
+
! Content-Type: application/json
|
|
39
|
+
`;
|
|
40
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
rules: [
|
|
43
|
+
{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] },
|
|
44
|
+
{ path: "/b", headers: { but: "I'm okay!" }, unsetHeaders: [] },
|
|
45
|
+
],
|
|
46
|
+
invalid: [
|
|
47
|
+
{
|
|
48
|
+
line: `I'm invalid!`,
|
|
49
|
+
lineNumber: 7,
|
|
50
|
+
message: "Expected a colon-separated header pair (e.g. name: value)",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
line: "!x-content-type",
|
|
54
|
+
lineNumber: 8,
|
|
55
|
+
message: "Expected a colon-separated header pair (e.g. name: value)",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
line: `! Content-Type: application/json`,
|
|
59
|
+
lineNumber: 10,
|
|
60
|
+
message: "Header name cannot include spaces",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
test("parseHeaders should reject lines longer than 2000 chars", () => {
|
|
66
|
+
const huge_line = `${Array(1001).fill("a").join("")}: ${Array(1001)
|
|
67
|
+
.fill("b")
|
|
68
|
+
.join("")}`;
|
|
69
|
+
const input = `
|
|
70
|
+
# Valid entry
|
|
71
|
+
/a
|
|
72
|
+
Name: Value
|
|
73
|
+
# Jumbo comment line OK, ignored as normal
|
|
74
|
+
${Array(1001).fill("#").join("")}
|
|
75
|
+
# Huge path names rejected
|
|
76
|
+
/b
|
|
77
|
+
Name: Value
|
|
78
|
+
${huge_line}
|
|
79
|
+
`;
|
|
80
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
81
|
+
expect(result).toEqual({
|
|
82
|
+
rules: [
|
|
83
|
+
{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] },
|
|
84
|
+
{ path: "/b", headers: { name: "Value" }, unsetHeaders: [] },
|
|
85
|
+
],
|
|
86
|
+
invalid: [
|
|
87
|
+
{
|
|
88
|
+
message: `Ignoring line 10 as it exceeds the maximum allowed length of 2000.`,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
test("parseHeaders should reject any rules after the first 100", () => {
|
|
94
|
+
const input = `
|
|
95
|
+
# COMMENTS DON'T COUNT TOWARDS TOTAL VALID RULES
|
|
96
|
+
${Array(150)
|
|
97
|
+
.fill(undefined)
|
|
98
|
+
.map((_, i) => `/a/${i}\nx-index: ${i}`)
|
|
99
|
+
.join("\n")}
|
|
100
|
+
# BUT DO GET COUNTED AS TOTAL LINES SKIPPED
|
|
101
|
+
`;
|
|
102
|
+
expect((0, parseHeaders_1.parseHeaders)(input)).toEqual({
|
|
103
|
+
rules: Array(101)
|
|
104
|
+
.fill(undefined)
|
|
105
|
+
.map((_, i) => ({
|
|
106
|
+
path: "/a/" + i,
|
|
107
|
+
headers: { "x-index": `${i}` },
|
|
108
|
+
unsetHeaders: [],
|
|
109
|
+
})),
|
|
110
|
+
invalid: [
|
|
111
|
+
{
|
|
112
|
+
message: `Maximum number of rules supported is 100. Skipping remaining 100 lines of file.`,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
test("parseHeaders should reject malformed URLs", () => {
|
|
118
|
+
const input = `
|
|
119
|
+
# Spaces should be URI encoded
|
|
120
|
+
/some page with spaces
|
|
121
|
+
valid: yup
|
|
122
|
+
# OK with URL escaped encoding
|
|
123
|
+
/some%20page
|
|
124
|
+
valid: yup
|
|
125
|
+
# Unescaped URLs are handled OK by Deno, so escape & pass them through
|
|
126
|
+
/://so;\`me
|
|
127
|
+
valid: yup
|
|
128
|
+
/nons:/&@%+~{}ense
|
|
129
|
+
valid: yup
|
|
130
|
+
# Absolute URLs with a non-https protocol should be rejected
|
|
131
|
+
https://yeah.com
|
|
132
|
+
valid: yup
|
|
133
|
+
http://nah.com/blog
|
|
134
|
+
invalid: things
|
|
135
|
+
//yeah.com/blog
|
|
136
|
+
valid: things
|
|
137
|
+
/yeah
|
|
138
|
+
valid: yup
|
|
139
|
+
/yeah.com
|
|
140
|
+
valid: yup
|
|
141
|
+
# Anything standalone is interpreted as a invalid header pair
|
|
142
|
+
nah.com
|
|
143
|
+
:
|
|
144
|
+
test:
|
|
145
|
+
`;
|
|
146
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
147
|
+
expect(result).toEqual({
|
|
148
|
+
invalid: [
|
|
149
|
+
{
|
|
150
|
+
line: "http://nah.com/blog",
|
|
151
|
+
lineNumber: 16,
|
|
152
|
+
message: 'URLs should either be relative (e.g. begin with a forward-slash), or use HTTPS (e.g. begin with "https://").',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
line: "invalid: things",
|
|
156
|
+
lineNumber: 17,
|
|
157
|
+
message: "Path should come before header (invalid: things)",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
line: "nah.com",
|
|
161
|
+
lineNumber: 25,
|
|
162
|
+
message: "Expected a colon-separated header pair (e.g. name: value)",
|
|
163
|
+
},
|
|
164
|
+
{ line: ":", lineNumber: 26, message: "No header name specified" },
|
|
165
|
+
{ line: "test:", lineNumber: 27, message: "No header value specified" },
|
|
166
|
+
],
|
|
167
|
+
rules: [
|
|
168
|
+
{
|
|
169
|
+
path: "/some%20page%20with%20spaces",
|
|
170
|
+
headers: { valid: "yup" },
|
|
171
|
+
unsetHeaders: [],
|
|
172
|
+
},
|
|
173
|
+
{ path: "/some%20page", headers: { valid: "yup" }, unsetHeaders: [] },
|
|
174
|
+
{ path: "/://so;%60me", headers: { valid: "yup" }, unsetHeaders: [] },
|
|
175
|
+
{
|
|
176
|
+
path: "/nons:/&@%+~%7B%7Dense",
|
|
177
|
+
headers: { valid: "yup" },
|
|
178
|
+
unsetHeaders: [],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
path: "https://yeah.com/",
|
|
182
|
+
headers: { valid: "yup" },
|
|
183
|
+
unsetHeaders: [],
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
path: "//yeah.com/blog",
|
|
187
|
+
headers: { valid: "things" },
|
|
188
|
+
unsetHeaders: [],
|
|
189
|
+
},
|
|
190
|
+
{ path: "/yeah", headers: { valid: "yup" }, unsetHeaders: [] },
|
|
191
|
+
{ path: "/yeah.com", headers: { valid: "yup" }, unsetHeaders: [] },
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseHeaders.valid.test.d.ts","sourceRoot":"","sources":["../../../__tests__/metadata-generator/parseHeaders.valid.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const parseHeaders_1 = require("../..//metadata-generator/parseHeaders");
|
|
4
|
+
test("parseHeaders should handle a single rule", () => {
|
|
5
|
+
const input = `/a
|
|
6
|
+
Name: Value`;
|
|
7
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
8
|
+
expect(result).toEqual({
|
|
9
|
+
rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
|
|
10
|
+
invalid: [],
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
test("parseHeaders should handle headers with exclamation marks", () => {
|
|
14
|
+
const input = `/a
|
|
15
|
+
!Name: Value`;
|
|
16
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
17
|
+
expect(result).toEqual({
|
|
18
|
+
rules: [{ path: "/a", headers: { "!name": "Value" }, unsetHeaders: [] }],
|
|
19
|
+
invalid: [],
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
test("parseHeaders should ignore blank lines", () => {
|
|
23
|
+
const input = `
|
|
24
|
+
/a
|
|
25
|
+
|
|
26
|
+
Name: Value
|
|
27
|
+
|
|
28
|
+
`;
|
|
29
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
30
|
+
expect(result).toEqual({
|
|
31
|
+
rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
|
|
32
|
+
invalid: [],
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
test("parseHeaders should trim whitespace", () => {
|
|
36
|
+
const input = `
|
|
37
|
+
/a
|
|
38
|
+
Name : Value
|
|
39
|
+
`;
|
|
40
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
41
|
+
expect(result).toEqual({
|
|
42
|
+
rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
|
|
43
|
+
invalid: [],
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
test("parseHeaders should ignore comments", () => {
|
|
47
|
+
const input = `
|
|
48
|
+
# This is a comment
|
|
49
|
+
/a
|
|
50
|
+
# And one here too.
|
|
51
|
+
Name: Value
|
|
52
|
+
`;
|
|
53
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
54
|
+
expect(result).toEqual({
|
|
55
|
+
rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
|
|
56
|
+
invalid: [],
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
test("parseHeaders should combine headers together", () => {
|
|
60
|
+
const input = `
|
|
61
|
+
/a
|
|
62
|
+
Set-Cookie: test=cookie; expires=never
|
|
63
|
+
Set-Cookie: another=cookie; magic!
|
|
64
|
+
|
|
65
|
+
/b
|
|
66
|
+
A: ABBA
|
|
67
|
+
B: BABA
|
|
68
|
+
`;
|
|
69
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
70
|
+
expect(result).toEqual({
|
|
71
|
+
rules: [
|
|
72
|
+
{
|
|
73
|
+
path: "/a",
|
|
74
|
+
headers: {
|
|
75
|
+
"set-cookie": "test=cookie; expires=never, another=cookie; magic!",
|
|
76
|
+
},
|
|
77
|
+
unsetHeaders: [],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
path: "/b",
|
|
81
|
+
headers: { a: "ABBA", b: "BABA" },
|
|
82
|
+
unsetHeaders: [],
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
invalid: [],
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
test("parseHeaders should support setting hosts", () => {
|
|
89
|
+
const input = `
|
|
90
|
+
https://example.com
|
|
91
|
+
a: a
|
|
92
|
+
https://example.com/
|
|
93
|
+
b: b
|
|
94
|
+
https://example.com/blog
|
|
95
|
+
c: c
|
|
96
|
+
/blog
|
|
97
|
+
d:d
|
|
98
|
+
https://:subdomain.example.*/path
|
|
99
|
+
e:e
|
|
100
|
+
`;
|
|
101
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
102
|
+
expect(result).toEqual({
|
|
103
|
+
rules: [
|
|
104
|
+
{ path: "https://example.com/", headers: { a: "a" }, unsetHeaders: [] },
|
|
105
|
+
{ path: "https://example.com/", headers: { b: "b" }, unsetHeaders: [] },
|
|
106
|
+
{
|
|
107
|
+
path: "https://example.com/blog",
|
|
108
|
+
headers: { c: "c" },
|
|
109
|
+
unsetHeaders: [],
|
|
110
|
+
},
|
|
111
|
+
{ path: "/blog", headers: { d: "d" }, unsetHeaders: [] },
|
|
112
|
+
{
|
|
113
|
+
path: "https://:subdomain.example.*/path",
|
|
114
|
+
headers: { e: "e" },
|
|
115
|
+
unsetHeaders: [],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
invalid: [],
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
test("parseHeaders should add unset headers", () => {
|
|
122
|
+
const input = `/a
|
|
123
|
+
Name: Value
|
|
124
|
+
! Place`;
|
|
125
|
+
const result = (0, parseHeaders_1.parseHeaders)(input);
|
|
126
|
+
expect(result).toEqual({
|
|
127
|
+
rules: [
|
|
128
|
+
{ path: "/a", headers: { name: "Value" }, unsetHeaders: ["Place"] },
|
|
129
|
+
],
|
|
130
|
+
invalid: [],
|
|
131
|
+
});
|
|
132
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseRedirects.invalid.test.d.ts","sourceRoot":"","sources":["../../../__tests__/metadata-generator/parseRedirects.invalid.test.ts"],"names":[],"mappings":""}
|