wrangler 0.0.0-a8ea5c64 → 0.0.0-a96f2585
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/miniflare-dist/index.mjs +1157 -389
- package/package.json +15 -4
- package/src/__tests__/api-dev.test.ts +209 -0
- package/src/__tests__/api-devregistry.test.js +56 -0
- package/src/__tests__/api.test.ts +80 -0
- package/src/__tests__/configuration.test.ts +184 -346
- package/src/__tests__/dev.test.tsx +54 -16
- package/src/__tests__/dialogs.test.tsx +40 -0
- package/src/__tests__/helpers/mock-cfetch.ts +39 -19
- package/src/__tests__/helpers/mock-console.ts +11 -2
- package/src/__tests__/helpers/mock-oauth-flow.ts +4 -2
- package/src/__tests__/helpers/msw/handlers/index.ts +13 -0
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
- package/src/__tests__/helpers/msw/handlers/oauth.ts +36 -0
- package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
- package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
- package/src/__tests__/helpers/msw/index.ts +4 -0
- package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
- package/src/__tests__/helpers/worker-scripts/hello-world-worker.js +5 -0
- package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
- package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
- package/src/__tests__/index.test.ts +11 -7
- package/src/__tests__/init.test.ts +654 -8
- package/src/__tests__/jest.setup.ts +29 -0
- package/src/__tests__/middleware.scheduled.test.ts +135 -0
- package/src/__tests__/middleware.test.ts +726 -0
- package/src/__tests__/pages.test.ts +940 -104
- package/src/__tests__/paths.test.ts +39 -0
- package/src/__tests__/publish.test.ts +583 -448
- package/src/__tests__/r2.test.ts +128 -93
- package/src/__tests__/secret.test.ts +152 -0
- package/src/__tests__/tail.test.ts +47 -74
- package/src/__tests__/user.test.ts +4 -4
- package/src/__tests__/whoami.test.tsx +49 -65
- package/src/__tests__/worker-namespace.test.ts +102 -112
- package/src/api/dev.ts +148 -34
- package/src/api/index.ts +1 -0
- package/src/bundle.ts +296 -13
- package/src/cfetch/internal.ts +37 -21
- package/src/cli.ts +3 -1
- package/src/config/config.ts +12 -0
- package/src/config/environment.ts +20 -0
- package/src/config/index.ts +46 -4
- package/src/config/validation.ts +68 -0
- package/src/config-cache.ts +1 -1
- package/src/create-worker-preview.ts +21 -3
- package/src/create-worker-upload-form.ts +12 -2
- package/src/d1/backups.tsx +212 -0
- package/src/d1/create.tsx +54 -0
- package/src/d1/delete.tsx +56 -0
- package/src/d1/execute.tsx +294 -0
- package/src/d1/formatTimeAgo.ts +14 -0
- package/src/d1/index.ts +75 -0
- package/src/d1/list.tsx +48 -0
- package/src/d1/options.ts +12 -0
- package/src/d1/types.tsx +14 -0
- package/src/d1/utils.ts +39 -0
- package/src/dev/dev.tsx +57 -27
- package/src/dev/get-local-persistence-path.tsx +31 -0
- package/src/dev/local.tsx +426 -189
- package/src/dev/remote.tsx +280 -112
- package/src/dev/start-server.ts +506 -0
- package/src/dev/use-esbuild.ts +20 -1
- package/src/dev-registry.tsx +30 -0
- package/src/dev.tsx +205 -29
- package/src/dialogs.tsx +23 -0
- package/src/entry.ts +2 -1
- package/src/environment-variables.ts +17 -2
- package/src/index.tsx +130 -21
- package/src/init.ts +481 -132
- package/src/inspect.ts +26 -26
- package/src/logger.ts +11 -4
- package/src/metrics/send-event.ts +1 -0
- package/src/miniflare-cli/assets.ts +137 -476
- package/src/miniflare-cli/index.ts +50 -49
- package/src/module-collection.ts +9 -0
- package/src/pages/constants.ts +5 -1
- package/src/pages/dev.tsx +205 -46
- package/src/pages/errors.ts +48 -4
- package/src/pages/functions/buildPlugin.ts +2 -1
- package/src/pages/functions/buildWorker.ts +2 -1
- package/src/pages/functions/routes-transformation.test.ts +12 -1
- package/src/pages/functions/routes-transformation.ts +8 -15
- package/src/pages/functions/routes-validation.test.ts +403 -0
- package/src/pages/functions/routes-validation.ts +202 -0
- package/src/pages/functions.tsx +4 -18
- package/src/pages/hash.tsx +13 -0
- package/src/pages/publish.tsx +104 -59
- package/src/pages/upload.tsx +3 -18
- package/src/paths.ts +49 -4
- package/src/proxy.ts +336 -165
- package/src/publish.ts +61 -5
- package/src/tail/filters.ts +1 -5
- package/src/tail/index.ts +6 -3
- package/src/user/user.tsx +1 -0
- package/src/worker.ts +38 -8
- package/templates/d1-beta-facade.js +174 -0
- package/templates/experimental-local-cache-stubs.js +27 -0
- package/templates/init-tests/test-jest-new-worker.js +25 -0
- package/templates/init-tests/test-vitest-new-worker.js +26 -0
- package/templates/middleware/common.ts +62 -0
- package/templates/middleware/loader-modules.ts +84 -0
- package/templates/middleware/loader-sw.ts +213 -0
- package/templates/middleware/middleware-pretty-error.ts +40 -0
- package/templates/middleware/middleware-scheduled.ts +15 -0
- package/templates/new-worker.js +1 -1
- package/templates/pages-dev-pipeline.ts +35 -0
- package/wrangler-dist/cli.d.ts +513 -9
- package/wrangler-dist/cli.js +78375 -71653
- package/src/faye-websocket.d.ts +0 -6
- package/src/miniflare-cli/enum-keys.ts +0 -17
package/miniflare-dist/index.mjs
CHANGED
|
@@ -11,9 +11,16 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
11
11
|
return require.apply(this, arguments);
|
|
12
12
|
throw new Error('Dynamic require of "' + x + '" is not supported');
|
|
13
13
|
});
|
|
14
|
+
var __esm = (fn, res) => function __init() {
|
|
15
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
16
|
+
};
|
|
14
17
|
var __commonJS = (cb, mod) => function __require2() {
|
|
15
18
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
16
19
|
};
|
|
20
|
+
var __export = (target, all) => {
|
|
21
|
+
for (var name in all)
|
|
22
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
23
|
+
};
|
|
17
24
|
var __copyProps = (to, from, except, desc) => {
|
|
18
25
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
26
|
for (let key of __getOwnPropNames(from))
|
|
@@ -104,6 +111,634 @@ var require_mime = __commonJS({
|
|
|
104
111
|
}
|
|
105
112
|
});
|
|
106
113
|
|
|
114
|
+
// ../pages-shared/environment-polyfills/index.ts
|
|
115
|
+
var polyfill;
|
|
116
|
+
var init_environment_polyfills = __esm({
|
|
117
|
+
"../pages-shared/environment-polyfills/index.ts"() {
|
|
118
|
+
polyfill = (environment) => {
|
|
119
|
+
Object.entries(environment).map(([name, value]) => {
|
|
120
|
+
Object.defineProperty(globalThis, name, {
|
|
121
|
+
value,
|
|
122
|
+
configurable: true,
|
|
123
|
+
enumerable: true,
|
|
124
|
+
writable: true
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// ../pages-shared/environment-polyfills/miniflare.ts
|
|
132
|
+
var miniflare_exports = {};
|
|
133
|
+
import {
|
|
134
|
+
fetch as miniflareFetch,
|
|
135
|
+
Headers as MiniflareHeaders,
|
|
136
|
+
Request as MiniflareRequest,
|
|
137
|
+
Response as MiniflareResponse
|
|
138
|
+
} from "@miniflare/core";
|
|
139
|
+
var init_miniflare = __esm({
|
|
140
|
+
"../pages-shared/environment-polyfills/miniflare.ts"() {
|
|
141
|
+
init_environment_polyfills();
|
|
142
|
+
polyfill({
|
|
143
|
+
fetch: miniflareFetch,
|
|
144
|
+
Headers: MiniflareHeaders,
|
|
145
|
+
Request: MiniflareRequest,
|
|
146
|
+
Response: MiniflareResponse
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// ../pages-shared/asset-server/responses.ts
|
|
152
|
+
function mergeHeaders(base, extra) {
|
|
153
|
+
base = new Headers(base ?? {});
|
|
154
|
+
extra = new Headers(extra ?? {});
|
|
155
|
+
return new Headers({
|
|
156
|
+
...Object.fromEntries(base.entries()),
|
|
157
|
+
...Object.fromEntries(extra.entries())
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
var OkResponse, MovedPermanentlyResponse, FoundResponse, NotModifiedResponse, PermanentRedirectResponse, NotFoundResponse, MethodNotAllowedResponse, NotAcceptableResponse, InternalServerErrorResponse, SeeOtherResponse, TemporaryRedirectResponse;
|
|
161
|
+
var init_responses = __esm({
|
|
162
|
+
"../pages-shared/asset-server/responses.ts"() {
|
|
163
|
+
OkResponse = class extends Response {
|
|
164
|
+
constructor(...[body, init]) {
|
|
165
|
+
super(body, {
|
|
166
|
+
...init,
|
|
167
|
+
status: 200,
|
|
168
|
+
statusText: "OK"
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
MovedPermanentlyResponse = class extends Response {
|
|
173
|
+
constructor(location, init) {
|
|
174
|
+
super(`Redirecting to ${location}`, {
|
|
175
|
+
...init,
|
|
176
|
+
status: 301,
|
|
177
|
+
statusText: "Moved Permanently",
|
|
178
|
+
headers: mergeHeaders(init?.headers, {
|
|
179
|
+
location
|
|
180
|
+
})
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
FoundResponse = class extends Response {
|
|
185
|
+
constructor(location, init) {
|
|
186
|
+
super(`Redirecting to ${location}`, {
|
|
187
|
+
...init,
|
|
188
|
+
status: 302,
|
|
189
|
+
statusText: "Found",
|
|
190
|
+
headers: mergeHeaders(init?.headers, {
|
|
191
|
+
location
|
|
192
|
+
})
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
NotModifiedResponse = class extends Response {
|
|
197
|
+
constructor(...[_body, _init]) {
|
|
198
|
+
super(void 0, {
|
|
199
|
+
status: 304,
|
|
200
|
+
statusText: "Not Modified"
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
PermanentRedirectResponse = class extends Response {
|
|
205
|
+
constructor(location, init) {
|
|
206
|
+
super(void 0, {
|
|
207
|
+
...init,
|
|
208
|
+
status: 308,
|
|
209
|
+
statusText: "Permanent Redirect",
|
|
210
|
+
headers: mergeHeaders(init?.headers, {
|
|
211
|
+
location
|
|
212
|
+
})
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
NotFoundResponse = class extends Response {
|
|
217
|
+
constructor(...[body, init]) {
|
|
218
|
+
super(body, {
|
|
219
|
+
...init,
|
|
220
|
+
status: 404,
|
|
221
|
+
statusText: "Not Found"
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
MethodNotAllowedResponse = class extends Response {
|
|
226
|
+
constructor(...[body, init]) {
|
|
227
|
+
super(body, {
|
|
228
|
+
...init,
|
|
229
|
+
status: 405,
|
|
230
|
+
statusText: "Method Not Allowed"
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
NotAcceptableResponse = class extends Response {
|
|
235
|
+
constructor(...[body, init]) {
|
|
236
|
+
super(body, {
|
|
237
|
+
...init,
|
|
238
|
+
status: 406,
|
|
239
|
+
statusText: "Not Acceptable"
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
InternalServerErrorResponse = class extends Response {
|
|
244
|
+
constructor(err, init) {
|
|
245
|
+
let body = void 0;
|
|
246
|
+
if (globalThis.DEBUG) {
|
|
247
|
+
body = `${err.message}
|
|
248
|
+
|
|
249
|
+
${err.stack}`;
|
|
250
|
+
}
|
|
251
|
+
super(body, {
|
|
252
|
+
...init,
|
|
253
|
+
status: 500,
|
|
254
|
+
statusText: "Internal Server Error"
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
SeeOtherResponse = class extends Response {
|
|
259
|
+
constructor(location, init) {
|
|
260
|
+
super(`Redirecting to ${location}`, {
|
|
261
|
+
...init,
|
|
262
|
+
status: 303,
|
|
263
|
+
statusText: "See Other",
|
|
264
|
+
headers: mergeHeaders(init?.headers, { location })
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
TemporaryRedirectResponse = class extends Response {
|
|
269
|
+
constructor(location, init) {
|
|
270
|
+
super(`Redirecting to ${location}`, {
|
|
271
|
+
...init,
|
|
272
|
+
status: 307,
|
|
273
|
+
statusText: "Temporary Redirect",
|
|
274
|
+
headers: mergeHeaders(init?.headers, { location })
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// ../pages-shared/asset-server/rulesEngine.ts
|
|
282
|
+
var ESCAPE_REGEX_CHARACTERS, escapeRegex, HOST_PLACEHOLDER_REGEX, PLACEHOLDER_REGEX2, replacer, generateRulesMatcher;
|
|
283
|
+
var init_rulesEngine = __esm({
|
|
284
|
+
"../pages-shared/asset-server/rulesEngine.ts"() {
|
|
285
|
+
ESCAPE_REGEX_CHARACTERS = /[-/\\^$*+?.()|[\]{}]/g;
|
|
286
|
+
escapeRegex = (str) => {
|
|
287
|
+
return str.replace(ESCAPE_REGEX_CHARACTERS, "\\$&");
|
|
288
|
+
};
|
|
289
|
+
HOST_PLACEHOLDER_REGEX = /(?<=^https:\\\/\\\/[^/]*?):([^\\]+)(?=\\)/g;
|
|
290
|
+
PLACEHOLDER_REGEX2 = /:(\w+)/g;
|
|
291
|
+
replacer = (str, replacements) => {
|
|
292
|
+
for (const [replacement, value] of Object.entries(replacements)) {
|
|
293
|
+
str = str.replaceAll(`:${replacement}`, value);
|
|
294
|
+
}
|
|
295
|
+
return str;
|
|
296
|
+
};
|
|
297
|
+
generateRulesMatcher = (rules, replacerFn = (match) => match) => {
|
|
298
|
+
if (!rules)
|
|
299
|
+
return () => [];
|
|
300
|
+
const compiledRules = Object.entries(rules).map(([rule, match]) => {
|
|
301
|
+
const crossHost = rule.startsWith("https://");
|
|
302
|
+
rule = rule.split("*").map(escapeRegex).join("(?<splat>.*)");
|
|
303
|
+
const host_matches = rule.matchAll(HOST_PLACEHOLDER_REGEX);
|
|
304
|
+
for (const host_match of host_matches) {
|
|
305
|
+
rule = rule.split(host_match[0]).join(`(?<${host_match[1]}>[^/.]+)`);
|
|
306
|
+
}
|
|
307
|
+
const path_matches = rule.matchAll(PLACEHOLDER_REGEX2);
|
|
308
|
+
for (const path_match of path_matches) {
|
|
309
|
+
rule = rule.split(path_match[0]).join(`(?<${path_match[1]}>[^/]+)`);
|
|
310
|
+
}
|
|
311
|
+
rule = "^" + rule + "$";
|
|
312
|
+
try {
|
|
313
|
+
const regExp = new RegExp(rule);
|
|
314
|
+
return [{ crossHost, regExp }, match];
|
|
315
|
+
} catch {
|
|
316
|
+
}
|
|
317
|
+
}).filter((value) => value !== void 0);
|
|
318
|
+
return ({ request }) => {
|
|
319
|
+
const { pathname, host } = new URL(request.url);
|
|
320
|
+
return compiledRules.map(([{ crossHost, regExp }, match]) => {
|
|
321
|
+
const test = crossHost ? `https://${host}${pathname}` : pathname;
|
|
322
|
+
const result = regExp.exec(test);
|
|
323
|
+
if (result) {
|
|
324
|
+
return replacerFn(match, result.groups || {});
|
|
325
|
+
}
|
|
326
|
+
}).filter((value) => value !== void 0);
|
|
327
|
+
};
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// ../pages-shared/asset-server/handler.ts
|
|
333
|
+
var handler_exports = {};
|
|
334
|
+
__export(handler_exports, {
|
|
335
|
+
ANALYTICS_VERSION: () => ANALYTICS_VERSION2,
|
|
336
|
+
ASSET_PRESERVATION_CACHE: () => ASSET_PRESERVATION_CACHE,
|
|
337
|
+
CACHE_CONTROL_BROWSER: () => CACHE_CONTROL_BROWSER,
|
|
338
|
+
HEADERS_VERSION: () => HEADERS_VERSION2,
|
|
339
|
+
HEADERS_VERSION_V1: () => HEADERS_VERSION_V1,
|
|
340
|
+
REDIRECTS_VERSION: () => REDIRECTS_VERSION2,
|
|
341
|
+
generateHandler: () => generateHandler,
|
|
342
|
+
normaliseHeaders: () => normaliseHeaders,
|
|
343
|
+
parseQualityWeightedList: () => parseQualityWeightedList
|
|
344
|
+
});
|
|
345
|
+
function normaliseHeaders(headers) {
|
|
346
|
+
if (headers.version === HEADERS_VERSION2) {
|
|
347
|
+
return headers.rules;
|
|
348
|
+
} else if (headers.version === HEADERS_VERSION_V1) {
|
|
349
|
+
return Object.keys(headers.rules).reduce(
|
|
350
|
+
(acc, key) => {
|
|
351
|
+
acc[key] = {
|
|
352
|
+
set: headers.rules[key]
|
|
353
|
+
};
|
|
354
|
+
return acc;
|
|
355
|
+
},
|
|
356
|
+
{}
|
|
357
|
+
);
|
|
358
|
+
} else {
|
|
359
|
+
return {};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
async function generateHandler({
|
|
363
|
+
request,
|
|
364
|
+
metadata,
|
|
365
|
+
xServerEnvHeader,
|
|
366
|
+
logError,
|
|
367
|
+
findAssetEntryForPath,
|
|
368
|
+
getAssetKey,
|
|
369
|
+
negotiateContent,
|
|
370
|
+
fetchAsset,
|
|
371
|
+
generateNotFoundResponse = async (notFoundRequest, notFoundFindAssetEntryForPath, notFoundServeAsset) => {
|
|
372
|
+
let assetEntry;
|
|
373
|
+
if (assetEntry = await notFoundFindAssetEntryForPath("/index.html")) {
|
|
374
|
+
return notFoundServeAsset(assetEntry, { preserve: false });
|
|
375
|
+
}
|
|
376
|
+
return new NotFoundResponse();
|
|
377
|
+
},
|
|
378
|
+
attachAdditionalHeaders = () => {
|
|
379
|
+
},
|
|
380
|
+
caches,
|
|
381
|
+
waitUntil
|
|
382
|
+
}) {
|
|
383
|
+
const url = new URL(request.url);
|
|
384
|
+
const { protocol, host, search } = url;
|
|
385
|
+
let { pathname } = url;
|
|
386
|
+
const earlyHintsCache = metadata.deploymentId ? await caches?.open(`eh:${metadata.deploymentId}`) : void 0;
|
|
387
|
+
const headerRules = metadata.headers ? normaliseHeaders(metadata.headers) : {};
|
|
388
|
+
const staticRules = metadata.redirects?.version === REDIRECTS_VERSION2 ? metadata.redirects.staticRules || {} : {};
|
|
389
|
+
const staticRedirectsMatcher = () => {
|
|
390
|
+
const withHostMatch = staticRules[`https://${host}${pathname}`];
|
|
391
|
+
const withoutHostMatch = staticRules[pathname];
|
|
392
|
+
if (withHostMatch && withoutHostMatch) {
|
|
393
|
+
if (withHostMatch.lineNumber < withoutHostMatch.lineNumber) {
|
|
394
|
+
return withHostMatch;
|
|
395
|
+
} else {
|
|
396
|
+
return withoutHostMatch;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return withHostMatch || withoutHostMatch;
|
|
400
|
+
};
|
|
401
|
+
const generateRedirectsMatcher = () => generateRulesMatcher(
|
|
402
|
+
metadata.redirects?.version === REDIRECTS_VERSION2 ? metadata.redirects.rules : {},
|
|
403
|
+
({ status, to }, replacements) => ({
|
|
404
|
+
status,
|
|
405
|
+
to: replacer(to, replacements)
|
|
406
|
+
})
|
|
407
|
+
);
|
|
408
|
+
let assetEntry;
|
|
409
|
+
async function generateResponse() {
|
|
410
|
+
const match = staticRedirectsMatcher() || generateRedirectsMatcher()({ request })[0];
|
|
411
|
+
if (match) {
|
|
412
|
+
const { status, to } = match;
|
|
413
|
+
const destination = new URL(to, request.url);
|
|
414
|
+
const location = destination.origin === new URL(request.url).origin ? `${destination.pathname}${destination.search || search}${destination.hash}` : `${destination.href}${destination.search ? "" : search}${destination.hash}`;
|
|
415
|
+
switch (status) {
|
|
416
|
+
case 301:
|
|
417
|
+
return new MovedPermanentlyResponse(location);
|
|
418
|
+
case 303:
|
|
419
|
+
return new SeeOtherResponse(location);
|
|
420
|
+
case 307:
|
|
421
|
+
return new TemporaryRedirectResponse(location);
|
|
422
|
+
case 308:
|
|
423
|
+
return new PermanentRedirectResponse(location);
|
|
424
|
+
case 302:
|
|
425
|
+
default:
|
|
426
|
+
return new FoundResponse(location);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (!request.method.match(/^(get|head)$/i)) {
|
|
430
|
+
return new MethodNotAllowedResponse();
|
|
431
|
+
}
|
|
432
|
+
try {
|
|
433
|
+
pathname = globalThis.decodeURIComponent(pathname);
|
|
434
|
+
} catch (err) {
|
|
435
|
+
}
|
|
436
|
+
if (pathname.endsWith("/")) {
|
|
437
|
+
if (assetEntry = await findAssetEntryForPath(`${pathname}index.html`)) {
|
|
438
|
+
return serveAsset(assetEntry);
|
|
439
|
+
} else if (pathname.endsWith("/index/")) {
|
|
440
|
+
return new PermanentRedirectResponse(
|
|
441
|
+
`/${pathname.slice(1, -"index/".length)}${search}`
|
|
442
|
+
);
|
|
443
|
+
} else if (assetEntry = await findAssetEntryForPath(
|
|
444
|
+
`${pathname.replace(/\/$/, ".html")}`
|
|
445
|
+
)) {
|
|
446
|
+
return new PermanentRedirectResponse(
|
|
447
|
+
`/${pathname.slice(1, -1)}${search}`
|
|
448
|
+
);
|
|
449
|
+
} else {
|
|
450
|
+
return notFound();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (assetEntry = await findAssetEntryForPath(pathname)) {
|
|
454
|
+
if (pathname.endsWith(".html")) {
|
|
455
|
+
const extensionlessPath = pathname.slice(0, -".html".length);
|
|
456
|
+
if (extensionlessPath.endsWith("/index")) {
|
|
457
|
+
return new PermanentRedirectResponse(
|
|
458
|
+
`${extensionlessPath.replace(/\/index$/, "/")}${search}`
|
|
459
|
+
);
|
|
460
|
+
} else if (await findAssetEntryForPath(extensionlessPath) || extensionlessPath === "/") {
|
|
461
|
+
return serveAsset(assetEntry);
|
|
462
|
+
} else {
|
|
463
|
+
return new PermanentRedirectResponse(`${extensionlessPath}${search}`);
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
return serveAsset(assetEntry);
|
|
467
|
+
}
|
|
468
|
+
} else if (pathname.endsWith("/index")) {
|
|
469
|
+
return new PermanentRedirectResponse(
|
|
470
|
+
`/${pathname.slice(1, -"index".length)}${search}`
|
|
471
|
+
);
|
|
472
|
+
} else if (assetEntry = await findAssetEntryForPath(`${pathname}.html`)) {
|
|
473
|
+
return serveAsset(assetEntry);
|
|
474
|
+
} else if (hasFileExtension(pathname)) {
|
|
475
|
+
return notFound();
|
|
476
|
+
}
|
|
477
|
+
if (assetEntry = await findAssetEntryForPath(`${pathname}/index.html`)) {
|
|
478
|
+
return new PermanentRedirectResponse(`${pathname}/${search}`);
|
|
479
|
+
} else {
|
|
480
|
+
return notFound();
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
async function attachHeaders(response) {
|
|
484
|
+
const existingHeaders = new Headers(response.headers);
|
|
485
|
+
const extraHeaders = new Headers({
|
|
486
|
+
"access-control-allow-origin": "*",
|
|
487
|
+
"referrer-policy": "strict-origin-when-cross-origin",
|
|
488
|
+
...existingHeaders.has("content-type") ? { "x-content-type-options": "nosniff" } : {}
|
|
489
|
+
});
|
|
490
|
+
const headers = new Headers({
|
|
491
|
+
...Object.fromEntries(existingHeaders.entries()),
|
|
492
|
+
...Object.fromEntries(extraHeaders.entries())
|
|
493
|
+
});
|
|
494
|
+
if (earlyHintsCache) {
|
|
495
|
+
const preEarlyHintsHeaders = new Headers(headers);
|
|
496
|
+
const earlyHintsCacheKey = `${protocol}//${host}${pathname}`;
|
|
497
|
+
const earlyHintsResponse = await earlyHintsCache.match(
|
|
498
|
+
earlyHintsCacheKey
|
|
499
|
+
);
|
|
500
|
+
if (earlyHintsResponse) {
|
|
501
|
+
const earlyHintsLinkHeader = earlyHintsResponse.headers.get("Link");
|
|
502
|
+
if (earlyHintsLinkHeader) {
|
|
503
|
+
headers.set("Link", earlyHintsLinkHeader);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const clonedResponse = response.clone();
|
|
507
|
+
if (waitUntil) {
|
|
508
|
+
waitUntil(
|
|
509
|
+
(async () => {
|
|
510
|
+
try {
|
|
511
|
+
const links = [];
|
|
512
|
+
const transformedResponse = new HTMLRewriter().on("link[rel=preconnect],link[rel=preload]", {
|
|
513
|
+
element(element) {
|
|
514
|
+
for (const [attributeName] of element.attributes) {
|
|
515
|
+
if (!ALLOWED_EARLY_HINT_LINK_ATTRIBUTES.includes(
|
|
516
|
+
attributeName.toLowerCase()
|
|
517
|
+
)) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const href = element.getAttribute("href") || void 0;
|
|
522
|
+
const rel = element.getAttribute("rel") || void 0;
|
|
523
|
+
const as = element.getAttribute("as") || void 0;
|
|
524
|
+
if (href && !href.startsWith("data:") && rel) {
|
|
525
|
+
links.push({ href, rel, as });
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}).transform(clonedResponse);
|
|
529
|
+
await transformedResponse.text();
|
|
530
|
+
links.forEach(({ href, rel, as }) => {
|
|
531
|
+
let link = `<${href}>; rel="${rel}"`;
|
|
532
|
+
if (as) {
|
|
533
|
+
link += `; as=${as}`;
|
|
534
|
+
}
|
|
535
|
+
preEarlyHintsHeaders.append("Link", link);
|
|
536
|
+
});
|
|
537
|
+
const linkHeader = preEarlyHintsHeaders.get("Link");
|
|
538
|
+
if (linkHeader) {
|
|
539
|
+
await earlyHintsCache.put(
|
|
540
|
+
earlyHintsCacheKey,
|
|
541
|
+
new Response(null, { headers: { Link: linkHeader } })
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
} catch (err) {
|
|
545
|
+
}
|
|
546
|
+
})()
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const headersMatcher = generateRulesMatcher(
|
|
551
|
+
headerRules,
|
|
552
|
+
({ set = {}, unset = [] }, replacements) => {
|
|
553
|
+
const replacedSet = {};
|
|
554
|
+
Object.keys(set).forEach((key) => {
|
|
555
|
+
replacedSet[key] = replacer(set[key], replacements);
|
|
556
|
+
});
|
|
557
|
+
return {
|
|
558
|
+
set: replacedSet,
|
|
559
|
+
unset
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
);
|
|
563
|
+
const matches = headersMatcher({ request });
|
|
564
|
+
const setMap = /* @__PURE__ */ new Set();
|
|
565
|
+
matches.forEach(({ set = {}, unset = [] }) => {
|
|
566
|
+
Object.keys(set).forEach((key) => {
|
|
567
|
+
if (setMap.has(key.toLowerCase())) {
|
|
568
|
+
headers.append(key, set[key]);
|
|
569
|
+
} else {
|
|
570
|
+
headers.set(key, set[key]);
|
|
571
|
+
setMap.add(key.toLowerCase());
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
unset.forEach((key) => {
|
|
575
|
+
headers.delete(key);
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
return new Response(
|
|
579
|
+
[101, 204, 205, 304].includes(response.status) ? null : response.body,
|
|
580
|
+
{
|
|
581
|
+
headers,
|
|
582
|
+
status: response.status,
|
|
583
|
+
statusText: response.statusText
|
|
584
|
+
}
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
return await attachHeaders(await generateResponse());
|
|
588
|
+
async function serveAsset(servingAssetEntry, options = { preserve: true }) {
|
|
589
|
+
let content;
|
|
590
|
+
try {
|
|
591
|
+
content = negotiateContent(request, servingAssetEntry);
|
|
592
|
+
} catch (err) {
|
|
593
|
+
return new NotAcceptableResponse();
|
|
594
|
+
}
|
|
595
|
+
const assetKey = getAssetKey(servingAssetEntry, content);
|
|
596
|
+
const etag = `"${assetKey}"`;
|
|
597
|
+
const weakEtag = `W/${etag}`;
|
|
598
|
+
const ifNoneMatch = request.headers.get("if-none-match");
|
|
599
|
+
if (ifNoneMatch === weakEtag || ifNoneMatch === etag) {
|
|
600
|
+
return new NotModifiedResponse();
|
|
601
|
+
}
|
|
602
|
+
try {
|
|
603
|
+
const asset = await fetchAsset(assetKey);
|
|
604
|
+
const headers = {
|
|
605
|
+
etag,
|
|
606
|
+
"content-type": asset.contentType
|
|
607
|
+
};
|
|
608
|
+
let encodeBody = "automatic";
|
|
609
|
+
if (xServerEnvHeader) {
|
|
610
|
+
headers["x-server-env"] = xServerEnvHeader;
|
|
611
|
+
}
|
|
612
|
+
if (content.encoding) {
|
|
613
|
+
encodeBody = "manual";
|
|
614
|
+
headers["cache-control"] = "no-transform";
|
|
615
|
+
headers["content-encoding"] = content.encoding;
|
|
616
|
+
}
|
|
617
|
+
const response = new OkResponse(
|
|
618
|
+
request.method === "HEAD" ? null : asset.body,
|
|
619
|
+
{
|
|
620
|
+
headers,
|
|
621
|
+
encodeBody
|
|
622
|
+
}
|
|
623
|
+
);
|
|
624
|
+
if (isCacheable(request)) {
|
|
625
|
+
response.headers.append("cache-control", CACHE_CONTROL_BROWSER);
|
|
626
|
+
}
|
|
627
|
+
attachAdditionalHeaders(response, content, servingAssetEntry, asset);
|
|
628
|
+
if (isPreview(new URL(request.url))) {
|
|
629
|
+
response.headers.set("x-robots-tag", "noindex");
|
|
630
|
+
}
|
|
631
|
+
if (options.preserve) {
|
|
632
|
+
const preservedResponse = new Response(
|
|
633
|
+
[101, 204, 205, 304].includes(response.status) ? null : response.clone().body,
|
|
634
|
+
response
|
|
635
|
+
);
|
|
636
|
+
preservedResponse.headers.set(
|
|
637
|
+
"cache-control",
|
|
638
|
+
CACHE_CONTROL_PRESERVATION
|
|
639
|
+
);
|
|
640
|
+
preservedResponse.headers.set("x-robots-tag", "noindex");
|
|
641
|
+
if (waitUntil && caches) {
|
|
642
|
+
waitUntil(
|
|
643
|
+
caches.open(ASSET_PRESERVATION_CACHE).then(
|
|
644
|
+
(assetPreservationCache) => assetPreservationCache.put(request.url, preservedResponse)
|
|
645
|
+
).catch((err) => {
|
|
646
|
+
logError(err);
|
|
647
|
+
})
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
if (asset.contentType.startsWith("text/html") && metadata.analytics?.version === ANALYTICS_VERSION2) {
|
|
652
|
+
return new HTMLRewriter().on("body", {
|
|
653
|
+
element(e) {
|
|
654
|
+
e.append(
|
|
655
|
+
`<!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "${metadata.analytics?.token}"}'><\/script><!-- Cloudflare Pages Analytics -->`,
|
|
656
|
+
{ html: true }
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
}).transform(response);
|
|
660
|
+
}
|
|
661
|
+
return response;
|
|
662
|
+
} catch (err) {
|
|
663
|
+
logError(err);
|
|
664
|
+
return new InternalServerErrorResponse(err);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
async function notFound() {
|
|
668
|
+
if (caches) {
|
|
669
|
+
const assetPreservationCache = await caches.open(
|
|
670
|
+
ASSET_PRESERVATION_CACHE
|
|
671
|
+
);
|
|
672
|
+
const preservedResponse = await assetPreservationCache.match(request.url);
|
|
673
|
+
if (preservedResponse) {
|
|
674
|
+
return preservedResponse;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
let cwd = pathname;
|
|
678
|
+
while (cwd) {
|
|
679
|
+
cwd = cwd.slice(0, cwd.lastIndexOf("/"));
|
|
680
|
+
if (assetEntry = await findAssetEntryForPath(`${cwd}/404.html`)) {
|
|
681
|
+
let content;
|
|
682
|
+
try {
|
|
683
|
+
content = negotiateContent(request, assetEntry);
|
|
684
|
+
} catch (err) {
|
|
685
|
+
return new NotAcceptableResponse();
|
|
686
|
+
}
|
|
687
|
+
const assetKey = getAssetKey(assetEntry, content);
|
|
688
|
+
try {
|
|
689
|
+
const { body, contentType } = await fetchAsset(assetKey);
|
|
690
|
+
const response = new NotFoundResponse(body);
|
|
691
|
+
response.headers.set("content-type", contentType);
|
|
692
|
+
return response;
|
|
693
|
+
} catch (err) {
|
|
694
|
+
logError(err);
|
|
695
|
+
return new InternalServerErrorResponse(err);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return await generateNotFoundResponse(
|
|
700
|
+
request,
|
|
701
|
+
findAssetEntryForPath,
|
|
702
|
+
serveAsset
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
function parseQualityWeightedList(list = "") {
|
|
707
|
+
const items = {};
|
|
708
|
+
list.replace(/\s/g, "").split(",").forEach((el) => {
|
|
709
|
+
const [item, weight] = el.split(";q=");
|
|
710
|
+
items[item] = weight ? parseFloat(weight) : 1;
|
|
711
|
+
});
|
|
712
|
+
return items;
|
|
713
|
+
}
|
|
714
|
+
function isCacheable(request) {
|
|
715
|
+
return !request.headers.has("authorization") && !request.headers.has("range");
|
|
716
|
+
}
|
|
717
|
+
function hasFileExtension(path) {
|
|
718
|
+
return /\/.+\.[a-z0-9]+$/i.test(path);
|
|
719
|
+
}
|
|
720
|
+
function isPreview(url) {
|
|
721
|
+
if (url.hostname.endsWith(".pages.dev")) {
|
|
722
|
+
return url.hostname.split(".").length > 3 ? true : false;
|
|
723
|
+
}
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
var ASSET_PRESERVATION_CACHE, CACHE_CONTROL_PRESERVATION, CACHE_CONTROL_BROWSER, REDIRECTS_VERSION2, HEADERS_VERSION2, HEADERS_VERSION_V1, ANALYTICS_VERSION2, ALLOWED_EARLY_HINT_LINK_ATTRIBUTES;
|
|
727
|
+
var init_handler = __esm({
|
|
728
|
+
"../pages-shared/asset-server/handler.ts"() {
|
|
729
|
+
init_responses();
|
|
730
|
+
init_rulesEngine();
|
|
731
|
+
ASSET_PRESERVATION_CACHE = "assetPreservationCache";
|
|
732
|
+
CACHE_CONTROL_PRESERVATION = "public, s-maxage=604800";
|
|
733
|
+
CACHE_CONTROL_BROWSER = "public, max-age=0, must-revalidate";
|
|
734
|
+
REDIRECTS_VERSION2 = 1;
|
|
735
|
+
HEADERS_VERSION2 = 2;
|
|
736
|
+
HEADERS_VERSION_V1 = 1;
|
|
737
|
+
ANALYTICS_VERSION2 = 1;
|
|
738
|
+
ALLOWED_EARLY_HINT_LINK_ATTRIBUTES = ["rel", "as", "href"];
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
|
|
107
742
|
// src/miniflare-cli/index.ts
|
|
108
743
|
import { fetch } from "@miniflare/core";
|
|
109
744
|
import {
|
|
@@ -112,10 +747,9 @@ import {
|
|
|
112
747
|
} from "@miniflare/durable-objects";
|
|
113
748
|
import {
|
|
114
749
|
Log,
|
|
115
|
-
LogLevel,
|
|
116
750
|
Miniflare,
|
|
117
|
-
Response as
|
|
118
|
-
Request as
|
|
751
|
+
Response as MiniflareResponse3,
|
|
752
|
+
Request as MiniflareRequest3
|
|
119
753
|
} from "miniflare";
|
|
120
754
|
|
|
121
755
|
// ../../node_modules/yargs/lib/platform-shims/esm.mjs
|
|
@@ -4934,412 +5568,555 @@ var FatalError = class extends Error {
|
|
|
4934
5568
|
};
|
|
4935
5569
|
|
|
4936
5570
|
// src/miniflare-cli/assets.ts
|
|
4937
|
-
|
|
4938
|
-
import { existsSync, lstatSync, readFileSync as readFileSync4 } from "node:fs";
|
|
5571
|
+
import { existsSync, lstatSync, readFileSync as readFileSync5 } from "node:fs";
|
|
4939
5572
|
import { join } from "node:path";
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
5573
|
+
|
|
5574
|
+
// ../pages-shared/metadata-generator/constants.ts
|
|
5575
|
+
var REDIRECTS_VERSION = 1;
|
|
5576
|
+
var HEADERS_VERSION = 2;
|
|
5577
|
+
var ANALYTICS_VERSION = 1;
|
|
5578
|
+
var PERMITTED_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
5579
|
+
var HEADER_SEPARATOR = ":";
|
|
5580
|
+
var MAX_LINE_LENGTH = 2e3;
|
|
5581
|
+
var MAX_HEADER_RULES = 100;
|
|
5582
|
+
var MAX_DYNAMIC_REDIRECT_RULES = 100;
|
|
5583
|
+
var MAX_STATIC_REDIRECT_RULES = 2e3;
|
|
5584
|
+
var UNSET_OPERATOR = "! ";
|
|
5585
|
+
var SPLAT_REGEX = /\*/g;
|
|
5586
|
+
var PLACEHOLDER_REGEX = /:\w+/g;
|
|
5587
|
+
|
|
5588
|
+
// ../pages-shared/metadata-generator/createMetadataObject.ts
|
|
5589
|
+
function createMetadataObject({
|
|
5590
|
+
redirects,
|
|
5591
|
+
headers,
|
|
5592
|
+
webAnalyticsToken,
|
|
5593
|
+
deploymentId,
|
|
5594
|
+
logger = (_message) => {
|
|
5595
|
+
}
|
|
5596
|
+
}) {
|
|
5597
|
+
return {
|
|
5598
|
+
...constructRedirects({ redirects, logger }),
|
|
5599
|
+
...constructHeaders({ headers, logger }),
|
|
5600
|
+
...constructWebAnalytics({ webAnalyticsToken, logger }),
|
|
5601
|
+
deploymentId
|
|
5602
|
+
};
|
|
5603
|
+
}
|
|
5604
|
+
function constructRedirects({
|
|
5605
|
+
redirects,
|
|
5606
|
+
logger
|
|
5607
|
+
}) {
|
|
5608
|
+
if (!redirects)
|
|
5609
|
+
return {};
|
|
5610
|
+
const num_valid = redirects.rules.length;
|
|
5611
|
+
const num_invalid = redirects.invalid.length;
|
|
5612
|
+
logger(
|
|
5613
|
+
`Parsed ${num_valid} valid redirect rule${num_valid === 1 ? "" : "s"}.`
|
|
5614
|
+
);
|
|
5615
|
+
if (num_invalid > 0) {
|
|
5616
|
+
logger(`Found invalid redirect lines:`);
|
|
5617
|
+
for (const { line, lineNumber, message } of redirects.invalid) {
|
|
5618
|
+
if (line)
|
|
5619
|
+
logger(` - ${lineNumber ? `#${lineNumber}: ` : ""}${line}`);
|
|
5620
|
+
logger(` ${message}`);
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
if (num_valid === 0) {
|
|
5624
|
+
return {};
|
|
5625
|
+
}
|
|
5626
|
+
const staticRedirects = {};
|
|
5627
|
+
const dynamicRedirects = {};
|
|
5628
|
+
let canCreateStaticRule = true;
|
|
5629
|
+
for (const rule of redirects.rules) {
|
|
5630
|
+
if (!rule.from.match(SPLAT_REGEX) && !rule.from.match(PLACEHOLDER_REGEX)) {
|
|
5631
|
+
if (canCreateStaticRule) {
|
|
5632
|
+
staticRedirects[rule.from] = { status: rule.status, to: rule.to };
|
|
5633
|
+
continue;
|
|
5634
|
+
} else {
|
|
5635
|
+
logger(
|
|
5636
|
+
`Info: the redirect rule ${rule.from} \u2192 ${rule.status} ${rule.to} could be made more performant by bringing it above any lines with splats or placeholders.`
|
|
4965
5637
|
);
|
|
4966
5638
|
}
|
|
4967
5639
|
}
|
|
5640
|
+
dynamicRedirects[rule.from] = { status: rule.status, to: rule.to };
|
|
5641
|
+
canCreateStaticRule = false;
|
|
5642
|
+
}
|
|
5643
|
+
return {
|
|
5644
|
+
redirects: {
|
|
5645
|
+
version: REDIRECTS_VERSION,
|
|
5646
|
+
staticRules: staticRedirects,
|
|
5647
|
+
rules: dynamicRedirects
|
|
5648
|
+
}
|
|
4968
5649
|
};
|
|
4969
5650
|
}
|
|
4970
|
-
function
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
5651
|
+
function constructHeaders({
|
|
5652
|
+
headers,
|
|
5653
|
+
logger
|
|
5654
|
+
}) {
|
|
5655
|
+
if (!headers)
|
|
5656
|
+
return {};
|
|
5657
|
+
const num_valid = headers.rules.length;
|
|
5658
|
+
const num_invalid = headers.invalid.length;
|
|
5659
|
+
logger(`Parsed ${num_valid} valid header rule${num_valid === 1 ? "" : "s"}.`);
|
|
5660
|
+
if (num_invalid > 0) {
|
|
5661
|
+
logger(`Found invalid header lines:`);
|
|
5662
|
+
for (const { line, lineNumber, message } of headers.invalid) {
|
|
5663
|
+
if (line)
|
|
5664
|
+
logger(` - ${lineNumber ? `#${lineNumber}: ` : ""} ${line}`);
|
|
5665
|
+
logger(` ${message}`);
|
|
5666
|
+
}
|
|
4976
5667
|
}
|
|
4977
|
-
|
|
4978
|
-
}
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
const host_matches = rule.matchAll(
|
|
4986
|
-
/(?<=^https:\\\/\\\/[^/]*?):([^\\]+)(?=\\)/g
|
|
4987
|
-
);
|
|
4988
|
-
for (const hostMatch of host_matches) {
|
|
4989
|
-
rule = rule.split(hostMatch[0]).join(`(?<${hostMatch[1]}>[^/.]+)`);
|
|
5668
|
+
if (num_valid === 0) {
|
|
5669
|
+
return {};
|
|
5670
|
+
}
|
|
5671
|
+
const rules = {};
|
|
5672
|
+
for (const rule of headers.rules) {
|
|
5673
|
+
rules[rule.path] = {};
|
|
5674
|
+
if (Object.keys(rule.headers).length) {
|
|
5675
|
+
rules[rule.path].set = rule.headers;
|
|
4990
5676
|
}
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
rule = rule.split(pathMatch[0]).join(`(?<${pathMatch[1]}>[^/]+)`);
|
|
5677
|
+
if (rule.unsetHeaders.length) {
|
|
5678
|
+
rules[rule.path].unset = rule.unsetHeaders;
|
|
4994
5679
|
}
|
|
4995
|
-
rule = "^" + rule + "$";
|
|
4996
|
-
try {
|
|
4997
|
-
const regExp = new RegExp(rule);
|
|
4998
|
-
return [{ crossHost, regExp }, match];
|
|
4999
|
-
} catch {
|
|
5000
|
-
}
|
|
5001
|
-
}).filter((value) => value !== void 0);
|
|
5002
|
-
return ({ request }) => {
|
|
5003
|
-
const { pathname, host } = new URL(request.url);
|
|
5004
|
-
return compiledRules.map(([{ crossHost, regExp }, match]) => {
|
|
5005
|
-
const test = crossHost ? `https://${host}${pathname}` : pathname;
|
|
5006
|
-
const result = regExp.exec(test);
|
|
5007
|
-
if (result) {
|
|
5008
|
-
return replacerFn(match, result.groups || {});
|
|
5009
|
-
}
|
|
5010
|
-
}).filter((value) => value !== void 0);
|
|
5011
|
-
};
|
|
5012
|
-
}
|
|
5013
|
-
function generateHeadersMatcher(headersFile) {
|
|
5014
|
-
if (existsSync(headersFile)) {
|
|
5015
|
-
const contents = readFileSync4(headersFile).toString();
|
|
5016
|
-
const lines = contents.split("\n").map((line) => line.trim()).filter((line) => !line.startsWith("#") && line !== "");
|
|
5017
|
-
const rules = {};
|
|
5018
|
-
let rule = void 0;
|
|
5019
|
-
for (const line of lines) {
|
|
5020
|
-
if (/^([^\s]+:\/\/|^\/)/.test(line)) {
|
|
5021
|
-
if (rule && Object.keys(rule.headers).length > 0) {
|
|
5022
|
-
rules[rule.path] = rule.headers;
|
|
5023
|
-
}
|
|
5024
|
-
const path = validateURL(line);
|
|
5025
|
-
if (path) {
|
|
5026
|
-
rule = {
|
|
5027
|
-
path,
|
|
5028
|
-
headers: {}
|
|
5029
|
-
};
|
|
5030
|
-
continue;
|
|
5031
|
-
}
|
|
5032
|
-
}
|
|
5033
|
-
if (!line.includes(":"))
|
|
5034
|
-
continue;
|
|
5035
|
-
const [rawName, ...rawValue] = line.split(":");
|
|
5036
|
-
const name = rawName.trim().toLowerCase();
|
|
5037
|
-
const value = rawValue.join(":").trim();
|
|
5038
|
-
if (name === "")
|
|
5039
|
-
continue;
|
|
5040
|
-
if (!rule)
|
|
5041
|
-
continue;
|
|
5042
|
-
const existingValues = rule.headers[name];
|
|
5043
|
-
rule.headers[name] = existingValues ? `${existingValues}, ${value}` : value;
|
|
5044
|
-
}
|
|
5045
|
-
if (rule && Object.keys(rule.headers).length > 0) {
|
|
5046
|
-
rules[rule.path] = rule.headers;
|
|
5047
|
-
}
|
|
5048
|
-
const rulesMatcher = generateRulesMatcher(
|
|
5049
|
-
rules,
|
|
5050
|
-
(match, replacements) => Object.fromEntries(
|
|
5051
|
-
Object.entries(match).map(([name, value]) => [
|
|
5052
|
-
name,
|
|
5053
|
-
replacer(value, replacements)
|
|
5054
|
-
])
|
|
5055
|
-
)
|
|
5056
|
-
);
|
|
5057
|
-
return (request) => {
|
|
5058
|
-
const matches = rulesMatcher({
|
|
5059
|
-
request
|
|
5060
|
-
});
|
|
5061
|
-
if (matches)
|
|
5062
|
-
return matches;
|
|
5063
|
-
};
|
|
5064
|
-
} else {
|
|
5065
|
-
return () => void 0;
|
|
5066
5680
|
}
|
|
5681
|
+
return {
|
|
5682
|
+
headers: {
|
|
5683
|
+
version: HEADERS_VERSION,
|
|
5684
|
+
rules
|
|
5685
|
+
}
|
|
5686
|
+
};
|
|
5067
5687
|
}
|
|
5068
|
-
function
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
}).filter((rule) => rule !== void 0)
|
|
5080
|
-
);
|
|
5081
|
-
const rulesMatcher = generateRulesMatcher(
|
|
5082
|
-
rules,
|
|
5083
|
-
({ status, to }, replacements) => ({
|
|
5084
|
-
status,
|
|
5085
|
-
to: replacer(to, replacements)
|
|
5086
|
-
})
|
|
5087
|
-
);
|
|
5088
|
-
return (request) => {
|
|
5089
|
-
const match = rulesMatcher({
|
|
5090
|
-
request
|
|
5091
|
-
})[0];
|
|
5092
|
-
if (match)
|
|
5093
|
-
return match;
|
|
5094
|
-
};
|
|
5095
|
-
} else {
|
|
5096
|
-
return () => void 0;
|
|
5097
|
-
}
|
|
5688
|
+
function constructWebAnalytics({
|
|
5689
|
+
webAnalyticsToken
|
|
5690
|
+
}) {
|
|
5691
|
+
if (!webAnalyticsToken)
|
|
5692
|
+
return {};
|
|
5693
|
+
return {
|
|
5694
|
+
analytics: {
|
|
5695
|
+
version: ANALYTICS_VERSION,
|
|
5696
|
+
token: webAnalyticsToken
|
|
5697
|
+
}
|
|
5698
|
+
};
|
|
5098
5699
|
}
|
|
5099
|
-
|
|
5700
|
+
|
|
5701
|
+
// ../pages-shared/metadata-generator/validateURL.ts
|
|
5702
|
+
var extractPathname = (path = "/", includeSearch, includeHash) => {
|
|
5100
5703
|
if (!path.startsWith("/"))
|
|
5101
5704
|
path = `/${path}`;
|
|
5102
5705
|
const url = new URL(`//${path}`, "relative://");
|
|
5103
5706
|
return `${url.pathname}${includeSearch ? url.search : ""}${includeHash ? url.hash : ""}`;
|
|
5104
|
-
}
|
|
5105
|
-
|
|
5106
|
-
|
|
5707
|
+
};
|
|
5708
|
+
var URL_REGEX = /^https:\/\/+(?<host>[^/]+)\/?(?<path>.*)/;
|
|
5709
|
+
var PATH_REGEX = /^\//;
|
|
5710
|
+
var validateUrl = (token, onlyRelative = false, includeSearch = false, includeHash = false) => {
|
|
5711
|
+
const host = URL_REGEX.exec(token);
|
|
5107
5712
|
if (host && host.groups && host.groups.host) {
|
|
5108
5713
|
if (onlyRelative)
|
|
5109
|
-
return
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5714
|
+
return [
|
|
5715
|
+
void 0,
|
|
5716
|
+
`Only relative URLs are allowed. Skipping absolute URL ${token}.`
|
|
5717
|
+
];
|
|
5718
|
+
return [
|
|
5719
|
+
`https://${host.groups.host}${extractPathname(
|
|
5720
|
+
host.groups.path,
|
|
5721
|
+
includeSearch,
|
|
5722
|
+
includeHash
|
|
5723
|
+
)}`,
|
|
5724
|
+
void 0
|
|
5725
|
+
];
|
|
5115
5726
|
} else {
|
|
5116
5727
|
if (!token.startsWith("/") && onlyRelative)
|
|
5117
5728
|
token = `/${token}`;
|
|
5118
|
-
const path =
|
|
5729
|
+
const path = PATH_REGEX.exec(token);
|
|
5119
5730
|
if (path) {
|
|
5120
5731
|
try {
|
|
5121
|
-
return extractPathname(token, includeSearch, includeHash);
|
|
5732
|
+
return [extractPathname(token, includeSearch, includeHash), void 0];
|
|
5122
5733
|
} catch {
|
|
5734
|
+
return [void 0, `Error parsing URL segment ${token}. Skipping.`];
|
|
5123
5735
|
}
|
|
5124
5736
|
}
|
|
5125
5737
|
}
|
|
5126
|
-
return
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
}
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
const
|
|
5136
|
-
const
|
|
5137
|
-
const
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5738
|
+
return [
|
|
5739
|
+
void 0,
|
|
5740
|
+
onlyRelative ? "URLs should begin with a forward-slash." : 'URLs should either be relative (e.g. begin with a forward-slash), or use HTTPS (e.g. begin with "https://").'
|
|
5741
|
+
];
|
|
5742
|
+
};
|
|
5743
|
+
|
|
5744
|
+
// ../pages-shared/metadata-generator/parseHeaders.ts
|
|
5745
|
+
var LINE_IS_PROBABLY_A_PATH = new RegExp(/^([^\s]+:\/\/|^\/)/);
|
|
5746
|
+
function parseHeaders(input) {
|
|
5747
|
+
const lines = input.split("\n");
|
|
5748
|
+
const rules = [];
|
|
5749
|
+
const invalid = [];
|
|
5750
|
+
let rule = void 0;
|
|
5751
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5752
|
+
const line = lines[i].trim();
|
|
5753
|
+
if (line.length === 0 || line.startsWith("#"))
|
|
5754
|
+
continue;
|
|
5755
|
+
if (line.length > MAX_LINE_LENGTH) {
|
|
5756
|
+
invalid.push({
|
|
5757
|
+
message: `Ignoring line ${i + 1} as it exceeds the maximum allowed length of ${MAX_LINE_LENGTH}.`
|
|
5758
|
+
});
|
|
5759
|
+
continue;
|
|
5144
5760
|
}
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
}).on("change", (path) => {
|
|
5151
|
-
switch (path) {
|
|
5152
|
-
case headersFile: {
|
|
5153
|
-
log.log("_headers modified. Re-evaluating...");
|
|
5154
|
-
headersMatcher = generateHeadersMatcher(headersFile);
|
|
5761
|
+
if (LINE_IS_PROBABLY_A_PATH.test(line)) {
|
|
5762
|
+
if (rules.length >= MAX_HEADER_RULES) {
|
|
5763
|
+
invalid.push({
|
|
5764
|
+
message: `Maximum number of rules supported is ${MAX_HEADER_RULES}. Skipping remaining ${lines.length - i} lines of file.`
|
|
5765
|
+
});
|
|
5155
5766
|
break;
|
|
5156
5767
|
}
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5768
|
+
if (rule) {
|
|
5769
|
+
if (isValidRule(rule)) {
|
|
5770
|
+
rules.push({
|
|
5771
|
+
path: rule.path,
|
|
5772
|
+
headers: rule.headers,
|
|
5773
|
+
unsetHeaders: rule.unsetHeaders
|
|
5774
|
+
});
|
|
5775
|
+
} else {
|
|
5776
|
+
invalid.push({
|
|
5777
|
+
line: rule.line,
|
|
5778
|
+
lineNumber: i + 1,
|
|
5779
|
+
message: "No headers specified"
|
|
5780
|
+
});
|
|
5781
|
+
}
|
|
5161
5782
|
}
|
|
5783
|
+
const [path, pathError] = validateUrl(line);
|
|
5784
|
+
if (pathError) {
|
|
5785
|
+
invalid.push({
|
|
5786
|
+
line,
|
|
5787
|
+
lineNumber: i + 1,
|
|
5788
|
+
message: pathError
|
|
5789
|
+
});
|
|
5790
|
+
rule = void 0;
|
|
5791
|
+
continue;
|
|
5792
|
+
}
|
|
5793
|
+
rule = {
|
|
5794
|
+
path,
|
|
5795
|
+
line,
|
|
5796
|
+
headers: {},
|
|
5797
|
+
unsetHeaders: []
|
|
5798
|
+
};
|
|
5799
|
+
continue;
|
|
5162
5800
|
}
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5801
|
+
if (!line.includes(HEADER_SEPARATOR)) {
|
|
5802
|
+
if (!rule) {
|
|
5803
|
+
invalid.push({
|
|
5804
|
+
line,
|
|
5805
|
+
lineNumber: i + 1,
|
|
5806
|
+
message: "Expected a path beginning with at least one forward-slash"
|
|
5807
|
+
});
|
|
5808
|
+
} else {
|
|
5809
|
+
if (line.trim().startsWith(UNSET_OPERATOR)) {
|
|
5810
|
+
rule.unsetHeaders.push(line.trim().replace(UNSET_OPERATOR, ""));
|
|
5811
|
+
} else {
|
|
5812
|
+
invalid.push({
|
|
5813
|
+
line,
|
|
5814
|
+
lineNumber: i + 1,
|
|
5815
|
+
message: "Expected a colon-separated header pair (e.g. name: value)"
|
|
5816
|
+
});
|
|
5817
|
+
}
|
|
5818
|
+
}
|
|
5819
|
+
continue;
|
|
5820
|
+
}
|
|
5821
|
+
const [rawName, ...rawValue] = line.split(HEADER_SEPARATOR);
|
|
5822
|
+
const name = rawName.trim().toLowerCase();
|
|
5823
|
+
if (name.includes(" ")) {
|
|
5824
|
+
invalid.push({
|
|
5825
|
+
line,
|
|
5826
|
+
lineNumber: i + 1,
|
|
5827
|
+
message: "Header name cannot include spaces"
|
|
5828
|
+
});
|
|
5829
|
+
continue;
|
|
5830
|
+
}
|
|
5831
|
+
const value = rawValue.join(HEADER_SEPARATOR).trim();
|
|
5832
|
+
if (name === "") {
|
|
5833
|
+
invalid.push({
|
|
5834
|
+
line,
|
|
5835
|
+
lineNumber: i + 1,
|
|
5836
|
+
message: "No header name specified"
|
|
5837
|
+
});
|
|
5838
|
+
continue;
|
|
5839
|
+
}
|
|
5840
|
+
if (value === "") {
|
|
5841
|
+
invalid.push({
|
|
5842
|
+
line,
|
|
5843
|
+
lineNumber: i + 1,
|
|
5844
|
+
message: "No header value specified"
|
|
5845
|
+
});
|
|
5846
|
+
continue;
|
|
5847
|
+
}
|
|
5848
|
+
if (!rule) {
|
|
5849
|
+
invalid.push({
|
|
5850
|
+
line,
|
|
5851
|
+
lineNumber: i + 1,
|
|
5852
|
+
message: `Path should come before header (${name}: ${value})`
|
|
5853
|
+
});
|
|
5854
|
+
continue;
|
|
5855
|
+
}
|
|
5856
|
+
const existingValues = rule.headers[name];
|
|
5857
|
+
rule.headers[name] = existingValues ? `${existingValues}, ${value}` : value;
|
|
5858
|
+
}
|
|
5859
|
+
if (rule) {
|
|
5860
|
+
if (isValidRule(rule)) {
|
|
5861
|
+
rules.push({
|
|
5862
|
+
path: rule.path,
|
|
5863
|
+
headers: rule.headers,
|
|
5864
|
+
unsetHeaders: rule.unsetHeaders
|
|
5865
|
+
});
|
|
5866
|
+
} else {
|
|
5867
|
+
invalid.push({ line: rule.line, message: "No headers specified" });
|
|
5868
|
+
}
|
|
5869
|
+
}
|
|
5870
|
+
return {
|
|
5871
|
+
rules,
|
|
5872
|
+
invalid
|
|
5166
5873
|
};
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5874
|
+
}
|
|
5875
|
+
function isValidRule(rule) {
|
|
5876
|
+
return Object.keys(rule.headers).length > 0 || rule.unsetHeaders.length > 0;
|
|
5877
|
+
}
|
|
5878
|
+
|
|
5879
|
+
// ../pages-shared/metadata-generator/parseRedirects.ts
|
|
5880
|
+
function parseRedirects(input) {
|
|
5881
|
+
const lines = input.split("\n");
|
|
5882
|
+
const rules = [];
|
|
5883
|
+
const seen_paths = /* @__PURE__ */ new Set();
|
|
5884
|
+
const invalid = [];
|
|
5885
|
+
let staticRules = 0;
|
|
5886
|
+
let dynamicRules = 0;
|
|
5887
|
+
let canCreateStaticRule = true;
|
|
5888
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5889
|
+
const line = lines[i].trim();
|
|
5890
|
+
if (line.length === 0 || line.startsWith("#"))
|
|
5891
|
+
continue;
|
|
5892
|
+
if (line.length > MAX_LINE_LENGTH) {
|
|
5893
|
+
invalid.push({
|
|
5894
|
+
message: `Ignoring line ${i + 1} as it exceeds the maximum allowed length of ${MAX_LINE_LENGTH}.`
|
|
5895
|
+
});
|
|
5896
|
+
continue;
|
|
5173
5897
|
}
|
|
5174
|
-
const
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5898
|
+
const tokens = line.split(/\s+/);
|
|
5899
|
+
if (tokens.length < 2 || tokens.length > 3) {
|
|
5900
|
+
invalid.push({
|
|
5901
|
+
line,
|
|
5902
|
+
lineNumber: i + 1,
|
|
5903
|
+
message: `Expected exactly 2 or 3 whitespace-separated tokens. Got ${tokens.length}.`
|
|
5904
|
+
});
|
|
5905
|
+
continue;
|
|
5906
|
+
}
|
|
5907
|
+
const [str_from, str_to, str_status = "302"] = tokens;
|
|
5908
|
+
const fromResult = validateUrl(str_from, true, false, false);
|
|
5909
|
+
if (fromResult[0] === void 0) {
|
|
5910
|
+
invalid.push({
|
|
5911
|
+
line,
|
|
5912
|
+
lineNumber: i + 1,
|
|
5913
|
+
message: fromResult[1]
|
|
5914
|
+
});
|
|
5915
|
+
continue;
|
|
5916
|
+
}
|
|
5917
|
+
const from = fromResult[0];
|
|
5918
|
+
if (canCreateStaticRule && !from.match(SPLAT_REGEX) && !from.match(PLACEHOLDER_REGEX)) {
|
|
5919
|
+
staticRules += 1;
|
|
5920
|
+
if (staticRules > MAX_STATIC_REDIRECT_RULES) {
|
|
5921
|
+
invalid.push({
|
|
5922
|
+
message: `Maximum number of static rules supported is ${MAX_STATIC_REDIRECT_RULES}. Skipping line.`
|
|
5923
|
+
});
|
|
5924
|
+
continue;
|
|
5188
5925
|
}
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
}
|
|
5198
|
-
if (!request.method?.match(/^(get|head)$/i)) {
|
|
5199
|
-
deconstructedResponse.status = 405;
|
|
5200
|
-
return deconstructedResponse;
|
|
5201
|
-
}
|
|
5202
|
-
const notFound = () => {
|
|
5203
|
-
let cwd = assetName;
|
|
5204
|
-
while (cwd) {
|
|
5205
|
-
cwd = cwd.slice(0, cwd.lastIndexOf("/"));
|
|
5206
|
-
if (asset = getAsset(`${cwd}/404.html`)) {
|
|
5207
|
-
deconstructedResponse.status = 404;
|
|
5208
|
-
deconstructedResponse.body = serveAsset(asset);
|
|
5209
|
-
deconstructedResponse.headers.set(
|
|
5210
|
-
"Content-Type",
|
|
5211
|
-
(0, import_mime.getType)(asset) || "application/octet-stream"
|
|
5212
|
-
);
|
|
5213
|
-
return deconstructedResponse;
|
|
5214
|
-
}
|
|
5926
|
+
} else {
|
|
5927
|
+
dynamicRules += 1;
|
|
5928
|
+
canCreateStaticRule = false;
|
|
5929
|
+
if (dynamicRules > MAX_DYNAMIC_REDIRECT_RULES) {
|
|
5930
|
+
invalid.push({
|
|
5931
|
+
message: `Maximum number of dynamic rules supported is ${MAX_DYNAMIC_REDIRECT_RULES}. Skipping remaining ${lines.length - i} lines of file.`
|
|
5932
|
+
});
|
|
5933
|
+
break;
|
|
5215
5934
|
}
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5935
|
+
}
|
|
5936
|
+
const toResult = validateUrl(str_to, false, true, true);
|
|
5937
|
+
if (toResult[0] === void 0) {
|
|
5938
|
+
invalid.push({
|
|
5939
|
+
line,
|
|
5940
|
+
lineNumber: i + 1,
|
|
5941
|
+
message: toResult[1]
|
|
5942
|
+
});
|
|
5943
|
+
continue;
|
|
5944
|
+
}
|
|
5945
|
+
const to = toResult[0];
|
|
5946
|
+
const status = Number(str_status);
|
|
5947
|
+
if (isNaN(status) || !PERMITTED_STATUS_CODES.has(status)) {
|
|
5948
|
+
invalid.push({
|
|
5949
|
+
line,
|
|
5950
|
+
lineNumber: i + 1,
|
|
5951
|
+
message: `Valid status codes are 301, 302 (default), 303, 307, or 308. Got ${str_status}.`
|
|
5952
|
+
});
|
|
5953
|
+
continue;
|
|
5954
|
+
}
|
|
5955
|
+
if (seen_paths.has(from)) {
|
|
5956
|
+
invalid.push({
|
|
5957
|
+
line,
|
|
5958
|
+
lineNumber: i + 1,
|
|
5959
|
+
message: `Ignoring duplicate rule for path ${from}.`
|
|
5960
|
+
});
|
|
5961
|
+
continue;
|
|
5962
|
+
}
|
|
5963
|
+
seen_paths.add(from);
|
|
5964
|
+
rules.push({ from, to, status, lineNumber: i + 1 });
|
|
5965
|
+
}
|
|
5966
|
+
return {
|
|
5967
|
+
rules,
|
|
5968
|
+
invalid
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
|
|
5972
|
+
// src/miniflare-cli/assets.ts
|
|
5973
|
+
var import_mime = __toESM(require_mime());
|
|
5974
|
+
import { fetch as miniflareFetch2 } from "@miniflare/core";
|
|
5975
|
+
import {
|
|
5976
|
+
Response as MiniflareResponse2,
|
|
5977
|
+
Request as MiniflareRequest2
|
|
5978
|
+
} from "@miniflare/core";
|
|
5979
|
+
import { watch } from "chokidar";
|
|
5980
|
+
|
|
5981
|
+
// src/pages/hash.tsx
|
|
5982
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
5983
|
+
import { extname as extname2 } from "node:path";
|
|
5984
|
+
import { hash as blake3hash } from "blake3-wasm";
|
|
5985
|
+
var hashFile = (filepath) => {
|
|
5986
|
+
const contents = readFileSync4(filepath);
|
|
5987
|
+
const base64Contents = contents.toString("base64");
|
|
5988
|
+
const extension = extname2(filepath).substring(1);
|
|
5989
|
+
return blake3hash(base64Contents + extension).toString("hex").slice(0, 32);
|
|
5990
|
+
};
|
|
5991
|
+
|
|
5992
|
+
// src/miniflare-cli/assets.ts
|
|
5993
|
+
async function generateASSETSBinding(options) {
|
|
5994
|
+
const assetsFetch = options.directory !== void 0 ? await generateAssetsFetch(options.directory, options.log) : invalidAssetsFetch;
|
|
5995
|
+
return async function(miniflareRequest) {
|
|
5996
|
+
if (options.proxyPort) {
|
|
5997
|
+
try {
|
|
5998
|
+
const url = new URL(miniflareRequest.url);
|
|
5999
|
+
url.host = `localhost:${options.proxyPort}`;
|
|
6000
|
+
return await miniflareFetch2(url, miniflareRequest);
|
|
6001
|
+
} catch (thrown) {
|
|
6002
|
+
options.log.error(new Error(`Could not proxy request: ${thrown}`));
|
|
6003
|
+
return new MiniflareResponse2(
|
|
6004
|
+
`[wrangler] Could not proxy request: ${thrown}`,
|
|
6005
|
+
{
|
|
6006
|
+
status: 502
|
|
6007
|
+
}
|
|
5221
6008
|
);
|
|
5222
|
-
return deconstructedResponse;
|
|
5223
6009
|
}
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
"Content-Type",
|
|
5233
|
-
(0, import_mime.getType)(asset) || "application/octet-stream"
|
|
5234
|
-
);
|
|
5235
|
-
return deconstructedResponse;
|
|
5236
|
-
} else if (asset = getAsset(`${assetName.replace(/\/$/, ".html")}`)) {
|
|
5237
|
-
deconstructedResponse.status = 301;
|
|
5238
|
-
deconstructedResponse.headers.set(
|
|
5239
|
-
"Location",
|
|
5240
|
-
`${assetName.slice(0, -1)}${url.search}`
|
|
6010
|
+
} else {
|
|
6011
|
+
try {
|
|
6012
|
+
return await assetsFetch(miniflareRequest);
|
|
6013
|
+
} catch (thrown) {
|
|
6014
|
+
options.log.error(new Error(`Could not serve static asset: ${thrown}`));
|
|
6015
|
+
return new MiniflareResponse2(
|
|
6016
|
+
`[wrangler] Could not serve static asset: ${thrown}`,
|
|
6017
|
+
{ status: 502 }
|
|
5241
6018
|
);
|
|
5242
|
-
return deconstructedResponse;
|
|
5243
6019
|
}
|
|
5244
6020
|
}
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
6021
|
+
};
|
|
6022
|
+
}
|
|
6023
|
+
async function generateAssetsFetch(directory, log) {
|
|
6024
|
+
await Promise.resolve().then(() => (init_miniflare(), miniflare_exports));
|
|
6025
|
+
const { generateHandler: generateHandler2, parseQualityWeightedList: parseQualityWeightedList2 } = await Promise.resolve().then(() => (init_handler(), handler_exports));
|
|
6026
|
+
const headersFile = join(directory, "_headers");
|
|
6027
|
+
const redirectsFile = join(directory, "_redirects");
|
|
6028
|
+
const workerFile = join(directory, "_worker.js");
|
|
6029
|
+
const ignoredFiles = [headersFile, redirectsFile, workerFile];
|
|
6030
|
+
let redirects;
|
|
6031
|
+
if (existsSync(redirectsFile)) {
|
|
6032
|
+
const contents = readFileSync5(redirectsFile, "utf-8");
|
|
6033
|
+
redirects = parseRedirects(contents);
|
|
6034
|
+
}
|
|
6035
|
+
let headers;
|
|
6036
|
+
if (existsSync(headersFile)) {
|
|
6037
|
+
const contents = readFileSync5(headersFile, "utf-8");
|
|
6038
|
+
headers = parseHeaders(contents);
|
|
6039
|
+
}
|
|
6040
|
+
let metadata = createMetadataObject({
|
|
6041
|
+
redirects,
|
|
6042
|
+
headers,
|
|
6043
|
+
logger: log.warn.bind(log)
|
|
6044
|
+
});
|
|
6045
|
+
watch([headersFile, redirectsFile], { persistent: true }).on(
|
|
6046
|
+
"change",
|
|
6047
|
+
(path) => {
|
|
6048
|
+
switch (path) {
|
|
6049
|
+
case headersFile: {
|
|
6050
|
+
log.log("_headers modified. Re-evaluating...");
|
|
6051
|
+
const contents = readFileSync5(headersFile).toString();
|
|
6052
|
+
headers = parseHeaders(contents);
|
|
6053
|
+
break;
|
|
6054
|
+
}
|
|
6055
|
+
case redirectsFile: {
|
|
6056
|
+
log.log("_redirects modified. Re-evaluating...");
|
|
6057
|
+
const contents = readFileSync5(redirectsFile).toString();
|
|
6058
|
+
redirects = parseRedirects(contents);
|
|
6059
|
+
break;
|
|
6060
|
+
}
|
|
6061
|
+
}
|
|
6062
|
+
metadata = createMetadataObject({
|
|
6063
|
+
redirects,
|
|
6064
|
+
headers,
|
|
6065
|
+
logger: log.warn
|
|
6066
|
+
});
|
|
6067
|
+
}
|
|
6068
|
+
);
|
|
6069
|
+
const generateResponse = async (request) => {
|
|
6070
|
+
const assetKeyEntryMap = /* @__PURE__ */ new Map();
|
|
6071
|
+
return await generateHandler2({
|
|
6072
|
+
request,
|
|
6073
|
+
metadata,
|
|
6074
|
+
xServerEnvHeader: "dev",
|
|
6075
|
+
logError: console.error,
|
|
6076
|
+
findAssetEntryForPath: async (path) => {
|
|
6077
|
+
const filepath = join(directory, path);
|
|
6078
|
+
if (existsSync(filepath) && lstatSync(filepath).isFile() && !ignoredFiles.includes(filepath)) {
|
|
6079
|
+
const hash = hashFile(filepath);
|
|
6080
|
+
assetKeyEntryMap.set(hash, filepath);
|
|
6081
|
+
return hash;
|
|
6082
|
+
}
|
|
6083
|
+
return null;
|
|
6084
|
+
},
|
|
6085
|
+
getAssetKey: (assetEntry) => {
|
|
6086
|
+
return assetEntry;
|
|
6087
|
+
},
|
|
6088
|
+
negotiateContent: (contentRequest) => {
|
|
6089
|
+
let rawAcceptEncoding;
|
|
6090
|
+
if (contentRequest.cf && "clientAcceptEncoding" in contentRequest.cf && contentRequest.cf.clientAcceptEncoding) {
|
|
6091
|
+
rawAcceptEncoding = contentRequest.cf.clientAcceptEncoding;
|
|
5263
6092
|
} else {
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
6093
|
+
rawAcceptEncoding = contentRequest.headers.get("Accept-Encoding") || void 0;
|
|
6094
|
+
}
|
|
6095
|
+
const acceptEncoding = parseQualityWeightedList2(rawAcceptEncoding);
|
|
6096
|
+
if (acceptEncoding["identity"] === 0 || acceptEncoding["*"] === 0 && acceptEncoding["identity"] === void 0) {
|
|
6097
|
+
throw new Error("No acceptable encodings available");
|
|
6098
|
+
}
|
|
6099
|
+
return { encoding: null };
|
|
6100
|
+
},
|
|
6101
|
+
fetchAsset: async (assetKey) => {
|
|
6102
|
+
const filepath = assetKeyEntryMap.get(assetKey);
|
|
6103
|
+
if (!filepath) {
|
|
6104
|
+
throw new Error(
|
|
6105
|
+
"Could not fetch asset. Please file an issue on GitHub (https://github.com/cloudflare/wrangler2/issues/new/choose) with reproduction steps."
|
|
5268
6106
|
);
|
|
5269
|
-
return deconstructedResponse;
|
|
5270
6107
|
}
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
return deconstructedResponse;
|
|
5278
|
-
}
|
|
5279
|
-
} else if (hasFileExtension(assetName)) {
|
|
5280
|
-
if (asset = getAsset(assetName + ".html")) {
|
|
5281
|
-
deconstructedResponse.body = serveAsset(asset);
|
|
5282
|
-
deconstructedResponse.headers.set(
|
|
5283
|
-
"Content-Type",
|
|
5284
|
-
(0, import_mime.getType)(asset) || "application/octet-stream"
|
|
5285
|
-
);
|
|
5286
|
-
return deconstructedResponse;
|
|
6108
|
+
const body = readFileSync5(filepath);
|
|
6109
|
+
let contentType = (0, import_mime.getType)(filepath) || "application/octet-stream";
|
|
6110
|
+
if (contentType.startsWith("text/") && !contentType.includes("charset")) {
|
|
6111
|
+
contentType = `${contentType}; charset=utf-8`;
|
|
6112
|
+
}
|
|
6113
|
+
return { body, contentType };
|
|
5287
6114
|
}
|
|
5288
|
-
notFound();
|
|
5289
|
-
return deconstructedResponse;
|
|
5290
|
-
}
|
|
5291
|
-
if (asset = getAsset(`${assetName}.html`)) {
|
|
5292
|
-
deconstructedResponse.body = serveAsset(asset);
|
|
5293
|
-
deconstructedResponse.headers.set(
|
|
5294
|
-
"Content-Type",
|
|
5295
|
-
(0, import_mime.getType)(asset) || "application/octet-stream"
|
|
5296
|
-
);
|
|
5297
|
-
return deconstructedResponse;
|
|
5298
|
-
}
|
|
5299
|
-
if (asset = getAsset(`${assetName}/index.html`)) {
|
|
5300
|
-
deconstructedResponse.status = 301;
|
|
5301
|
-
deconstructedResponse.headers.set(
|
|
5302
|
-
"Location",
|
|
5303
|
-
`${assetName}/${url.search}`
|
|
5304
|
-
);
|
|
5305
|
-
return deconstructedResponse;
|
|
5306
|
-
} else {
|
|
5307
|
-
notFound();
|
|
5308
|
-
return deconstructedResponse;
|
|
5309
|
-
}
|
|
5310
|
-
};
|
|
5311
|
-
const attachHeaders = (request, deconstructedResponse) => {
|
|
5312
|
-
const headers = deconstructedResponse.headers;
|
|
5313
|
-
const newHeaders = new Headers({});
|
|
5314
|
-
const matches = headersMatcher(request) || [];
|
|
5315
|
-
matches.forEach((match) => {
|
|
5316
|
-
Object.entries(match).forEach(([name, value]) => {
|
|
5317
|
-
newHeaders.append(name, `${value}`);
|
|
5318
|
-
});
|
|
5319
|
-
});
|
|
5320
|
-
const combinedHeaders = {
|
|
5321
|
-
...Object.fromEntries(headers.entries()),
|
|
5322
|
-
...Object.fromEntries(newHeaders.entries())
|
|
5323
|
-
};
|
|
5324
|
-
deconstructedResponse.headers = new Headers({});
|
|
5325
|
-
Object.entries(combinedHeaders).forEach(([name, value]) => {
|
|
5326
|
-
if (value)
|
|
5327
|
-
deconstructedResponse.headers.set(name, value);
|
|
5328
6115
|
});
|
|
5329
6116
|
};
|
|
5330
6117
|
return async (input, init) => {
|
|
5331
|
-
const request = new
|
|
5332
|
-
|
|
5333
|
-
attachHeaders(request, deconstructedResponse);
|
|
5334
|
-
const headers = new Headers();
|
|
5335
|
-
[...deconstructedResponse.headers.entries()].forEach(([name, value]) => {
|
|
5336
|
-
if (value)
|
|
5337
|
-
headers.set(name, value);
|
|
5338
|
-
});
|
|
5339
|
-
return new Response(deconstructedResponse.body, {
|
|
5340
|
-
headers,
|
|
5341
|
-
status: deconstructedResponse.status
|
|
5342
|
-
});
|
|
6118
|
+
const request = new MiniflareRequest2(input, init);
|
|
6119
|
+
return await generateResponse(request);
|
|
5343
6120
|
};
|
|
5344
6121
|
}
|
|
5345
6122
|
var invalidAssetsFetch = () => {
|
|
@@ -5348,18 +6125,6 @@ var invalidAssetsFetch = () => {
|
|
|
5348
6125
|
);
|
|
5349
6126
|
};
|
|
5350
6127
|
|
|
5351
|
-
// src/miniflare-cli/enum-keys.ts
|
|
5352
|
-
var enumObject = (e) => {
|
|
5353
|
-
const copy = { ...e };
|
|
5354
|
-
Object.values(e).forEach(
|
|
5355
|
-
(value) => typeof value === "number" && delete copy[value]
|
|
5356
|
-
);
|
|
5357
|
-
return copy;
|
|
5358
|
-
};
|
|
5359
|
-
var enumKeys = (e) => {
|
|
5360
|
-
return Object.keys(enumObject(e));
|
|
5361
|
-
};
|
|
5362
|
-
|
|
5363
6128
|
// src/miniflare-cli/request-context.ts
|
|
5364
6129
|
var getRequestContextCheckOptions = async () => {
|
|
5365
6130
|
let hasAsyncLocalStorage = true;
|
|
@@ -5388,22 +6153,20 @@ var NoOpLog = class extends Log {
|
|
|
5388
6153
|
}
|
|
5389
6154
|
};
|
|
5390
6155
|
async function main() {
|
|
5391
|
-
const args = await yargs_default(hideBin(process.argv)).help(false).version(false).
|
|
5392
|
-
choices: enumKeys(LogLevel)
|
|
5393
|
-
}).argv;
|
|
5394
|
-
const logLevel = LogLevel[args.log ?? "INFO"];
|
|
6156
|
+
const args = await yargs_default(hideBin(process.argv)).help(false).version(false).argv;
|
|
5395
6157
|
const requestContextCheckOptions = await getRequestContextCheckOptions();
|
|
5396
6158
|
const config = {
|
|
5397
6159
|
...JSON.parse(args._[0] ?? "{}"),
|
|
5398
6160
|
...requestContextCheckOptions
|
|
5399
6161
|
};
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
6162
|
+
const logLevel = config.logLevel.toUpperCase();
|
|
6163
|
+
config.log = config.logLevel === "none" ? new NoOpLog() : new Log(logLevel, config.logOptions);
|
|
6164
|
+
if (logLevel === "DEBUG" || logLevel === "VERBOSE") {
|
|
6165
|
+
console.log("MINIFLARE OPTIONS:\n", JSON.stringify(config, null, 2));
|
|
5403
6166
|
}
|
|
5404
6167
|
config.bindings = {
|
|
5405
6168
|
...config.bindings,
|
|
5406
|
-
...Object.fromEntries(
|
|
6169
|
+
...config.externalDurableObjects && Object.fromEntries(
|
|
5407
6170
|
Object.entries(
|
|
5408
6171
|
config.externalDurableObjects
|
|
5409
6172
|
).map(([binding, { name, host, port }]) => {
|
|
@@ -5417,17 +6180,20 @@ async function main() {
|
|
|
5417
6180
|
namespace.get = (id) => {
|
|
5418
6181
|
const stub = new DurableObjectStub(factory, id);
|
|
5419
6182
|
stub.fetch = (...reqArgs) => {
|
|
5420
|
-
const requestFromArgs = new
|
|
6183
|
+
const requestFromArgs = new MiniflareRequest3(...reqArgs);
|
|
5421
6184
|
const url = new URL(requestFromArgs.url);
|
|
5422
6185
|
url.host = host;
|
|
5423
6186
|
if (port !== void 0)
|
|
5424
6187
|
url.port = port.toString();
|
|
5425
|
-
const request = new
|
|
6188
|
+
const request = new MiniflareRequest3(
|
|
5426
6189
|
url.toString(),
|
|
5427
6190
|
requestFromArgs
|
|
5428
6191
|
);
|
|
5429
6192
|
request.headers.set("x-miniflare-durable-object-name", name);
|
|
5430
|
-
request.headers.set(
|
|
6193
|
+
request.headers.set(
|
|
6194
|
+
"x-miniflare-durable-object-id",
|
|
6195
|
+
id.toString()
|
|
6196
|
+
);
|
|
5431
6197
|
return fetch(request);
|
|
5432
6198
|
};
|
|
5433
6199
|
return stub;
|
|
@@ -5460,7 +6226,8 @@ async function main() {
|
|
|
5460
6226
|
};
|
|
5461
6227
|
}
|
|
5462
6228
|
mf = new Miniflare(config);
|
|
5463
|
-
await mf.startServer();
|
|
6229
|
+
const mfServer = await mf.startServer();
|
|
6230
|
+
const mfPort = mfServer.address().port;
|
|
5464
6231
|
await mf.startScheduler();
|
|
5465
6232
|
const internalDurableObjectClassNames = Object.values(
|
|
5466
6233
|
config.durableObjects
|
|
@@ -5477,7 +6244,7 @@ async function main() {
|
|
|
5477
6244
|
}`,
|
|
5478
6245
|
serviceBindings: {
|
|
5479
6246
|
DO: async (request) => {
|
|
5480
|
-
request = new
|
|
6247
|
+
request = new MiniflareRequest3(request);
|
|
5481
6248
|
const name = request.headers.get("x-miniflare-durable-object-name");
|
|
5482
6249
|
const idString = request.headers.get(
|
|
5483
6250
|
"x-miniflare-durable-object-id"
|
|
@@ -5485,7 +6252,7 @@ async function main() {
|
|
|
5485
6252
|
request.headers.delete("x-miniflare-durable-object-name");
|
|
5486
6253
|
request.headers.delete("x-miniflare-durable-object-id");
|
|
5487
6254
|
if (!name || !idString) {
|
|
5488
|
-
return new
|
|
6255
|
+
return new MiniflareResponse3(
|
|
5489
6256
|
"[durable-object-proxy-err] Missing `x-miniflare-durable-object-name` or `x-miniflare-durable-object-id` headers.",
|
|
5490
6257
|
{ status: 400 }
|
|
5491
6258
|
);
|
|
@@ -5493,14 +6260,14 @@ async function main() {
|
|
|
5493
6260
|
const namespace = await mf?.getDurableObjectNamespace(name);
|
|
5494
6261
|
const id = namespace?.idFromString(idString);
|
|
5495
6262
|
if (!id) {
|
|
5496
|
-
return new
|
|
6263
|
+
return new MiniflareResponse3(
|
|
5497
6264
|
"[durable-object-proxy-err] Could not generate an ID. Possibly due to a mismatched DO name and ID?",
|
|
5498
6265
|
{ status: 500 }
|
|
5499
6266
|
);
|
|
5500
6267
|
}
|
|
5501
6268
|
const stub = namespace?.get(id);
|
|
5502
6269
|
if (!stub) {
|
|
5503
|
-
return new
|
|
6270
|
+
return new MiniflareResponse3(
|
|
5504
6271
|
"[durable-object-proxy-err] Could not generate a stub. Possibly due to a mismatched DO name and ID?",
|
|
5505
6272
|
{ status: 500 }
|
|
5506
6273
|
);
|
|
@@ -5515,6 +6282,7 @@ async function main() {
|
|
|
5515
6282
|
}
|
|
5516
6283
|
process.send && process.send(
|
|
5517
6284
|
JSON.stringify({
|
|
6285
|
+
mfPort,
|
|
5518
6286
|
ready: true,
|
|
5519
6287
|
durableObjectsPort: durableObjectsMfPort
|
|
5520
6288
|
})
|