@qwik.dev/router 2.0.0-beta.43 → 2.0.0-beta.47
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/lib/adapters/azure-swa/vite/index.d.ts +2 -2
- package/lib/adapters/azure-swa/vite/index.mjs +2 -1
- package/lib/adapters/bun-server/vite/index.d.ts +2 -2
- package/lib/adapters/bun-server/vite/index.mjs +2 -1
- package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
- package/lib/adapters/cloud-run/vite/index.mjs +2 -1
- package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
- package/lib/adapters/cloudflare-pages/vite/index.mjs +2 -1
- package/lib/adapters/deno-server/vite/index.d.ts +2 -2
- package/lib/adapters/deno-server/vite/index.mjs +2 -1
- package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
- package/lib/adapters/netlify-edge/vite/index.mjs +2 -1
- package/lib/adapters/node-server/vite/index.d.ts +2 -2
- package/lib/adapters/node-server/vite/index.mjs +2 -1
- package/lib/adapters/shared/vite/index.d.ts +1 -1
- package/lib/adapters/shared/vite/index.mjs +36 -32
- package/lib/adapters/ssg/vite/index.d.ts +1 -1
- package/lib/adapters/ssg/vite/index.mjs +4 -2
- package/lib/adapters/vercel-edge/vite/index.d.ts +2 -2
- package/lib/adapters/vercel-edge/vite/index.mjs +18 -15
- package/lib/chunks/fs.mjs +28 -25
- package/lib/chunks/head.qwik.mjs +731 -448
- package/lib/chunks/http-error.qwik.mjs +8 -7
- package/lib/chunks/pathname.mjs +9 -8
- package/lib/chunks/request-path.mjs +8 -4
- package/lib/chunks/route-trie-key.mjs +10 -0
- package/lib/chunks/routes.mjs +14 -14
- package/lib/chunks/server-error.mjs +28 -6
- package/lib/chunks/{url.mjs → static-file.mjs} +12 -2
- package/lib/chunks/system.mjs +31 -25
- package/lib/chunks/user-response.mjs +455 -348
- package/lib/chunks/worker-thread.mjs +90 -88
- package/lib/index.d.ts +94 -63
- package/lib/index.qwik.mjs +615 -523
- package/lib/middleware/aws-lambda/index.mjs +6 -3
- package/lib/middleware/azure-swa/index.mjs +4 -2
- package/lib/middleware/bun/index.mjs +12 -12
- package/lib/middleware/cloudflare-pages/index.mjs +19 -4
- package/lib/middleware/deno/index.mjs +12 -12
- package/lib/middleware/firebase/index.mjs +4 -2
- package/lib/middleware/netlify-edge/index.mjs +4 -2
- package/lib/middleware/node/index.mjs +16 -15
- package/lib/middleware/request-handler/index.d.ts +102 -2
- package/lib/middleware/request-handler/index.mjs +30 -34
- package/lib/middleware/vercel-edge/index.mjs +4 -2
- package/lib/service-worker/index.mjs +2 -1
- package/lib/ssg/index.mjs +23 -18
- package/lib/vite/index.d.ts +1 -1
- package/lib/vite/index.mjs +669 -604
- package/package.json +5 -5
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { t as ensureSlash } from "./pathname.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { A as loadRouteLoader, D as getRouteLoaderValues, E as getRouteLoaderResponse, N as resolveRouteLoaderByHash, R as setRouteLoaders, T as getRouteLoaderParams, a as isPromise, at as RequestEvRouterConfig, f as FULLPATH_HEADER, g as clearRouteLoaderData, it as Q_ROUTE, j as matchesRouteLoaderId, nt as QDATA_KEY, ot as _asyncRequestStore, r as resolveRouteConfig, rt as QFN_KEY, tt as QACTION_KEY, w as getRouteLoaderCtx, x as getLoaderRequestEvent } from "./head.qwik.mjs";
|
|
3
3
|
import { a as QLoaderId, c as resolveValidInternalFullPathname, i as QActionId, s as recognizeRequest, t as IsQAction, u as trimRecognizedInternalPathname } from "./request-path.mjs";
|
|
4
|
-
import { i as RedirectMessage, n as throwIfControlFlowSignal, r as AbortMessage, t as ServerError } from "./server-error.mjs";
|
|
4
|
+
import { a as shareClassIdentity, i as RedirectMessage, n as throwIfControlFlowSignal, r as AbortMessage, t as ServerError } from "./server-error.mjs";
|
|
5
5
|
import { inlinedQrl, isDev } from "@qwik.dev/core";
|
|
6
6
|
import { _deserialize, _serialize, _verifySerializable, isDev as isDev$1 } from "@qwik.dev/core/internal";
|
|
7
7
|
/**
|
|
8
8
|
* FNV-1a 32-bit hash for generating eTags from response data. Cheap to compute, sufficient
|
|
9
9
|
* collision resistance for cache validation (not cryptographic).
|
|
10
|
-
*/
|
|
10
|
+
*/
|
|
11
|
+
function hash(str) {
|
|
11
12
|
let hash = 2166136261;
|
|
12
13
|
for (let i = 0; i < str.length; i++) {
|
|
13
14
|
hash ^= str.charCodeAt(i);
|
|
@@ -21,7 +22,8 @@ import { _deserialize, _serialize, _verifySerializable, isDev as isDev$1 } from
|
|
|
21
22
|
* character outside RFC 7232's `etagc` grammar (printable ASCII except DQUOTE — no escape mechanism
|
|
22
23
|
* exists, and non-ASCII bytes are mangled by many HTTP stacks even though `obs-text` technically
|
|
23
24
|
* permits them). Idempotent.
|
|
24
|
-
*/
|
|
25
|
+
*/
|
|
26
|
+
function normalizeETag(raw) {
|
|
25
27
|
let tag = raw.trim();
|
|
26
28
|
if (tag.endsWith("\"") && tag.startsWith("W/\"")) tag = tag.slice(3);
|
|
27
29
|
tag = tag.replace(/[^!#-~]/g, "");
|
|
@@ -35,7 +37,8 @@ function setETagHeader(requestEv, normalizedETag) {
|
|
|
35
37
|
* Set the strong ETag header on the response and check the request's `If-None-Match` against it.
|
|
36
38
|
* The eTag argument must already be normalized. Returns true if a 304 was sent (caller should stop
|
|
37
39
|
* processing).
|
|
38
|
-
*/
|
|
40
|
+
*/
|
|
41
|
+
function performETagMatch(requestEv, normalizedETag, beforeNotModified) {
|
|
39
42
|
setETagHeader(requestEv, normalizedETag);
|
|
40
43
|
const ifNoneMatch = requestEv.request.headers.get("If-None-Match");
|
|
41
44
|
if (ifNoneMatch) {
|
|
@@ -47,6 +50,7 @@ function setETagHeader(requestEv, normalizedETag) {
|
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
if (found) {
|
|
53
|
+
beforeNotModified?.();
|
|
50
54
|
requestEv.status(304);
|
|
51
55
|
requestEv.send(304, "");
|
|
52
56
|
return true;
|
|
@@ -100,6 +104,20 @@ var UNIT = {
|
|
|
100
104
|
days: 86400,
|
|
101
105
|
weeks: 604800
|
|
102
106
|
};
|
|
107
|
+
var createSetCookieValue = (cookieName, cookieValue, options) => {
|
|
108
|
+
const c = [`${cookieName}=${cookieValue}`];
|
|
109
|
+
if (typeof options.domain === "string") c.push(`Domain=${options.domain}`);
|
|
110
|
+
if (typeof options.maxAge === "number") c.push(`Max-Age=${options.maxAge}`);
|
|
111
|
+
else if (Array.isArray(options.maxAge)) c.push(`Max-Age=${options.maxAge[0] * UNIT[options.maxAge[1]]}`);
|
|
112
|
+
else if (typeof options.expires === "number" || typeof options.expires == "string") c.push(`Expires=${options.expires}`);
|
|
113
|
+
else if (options.expires instanceof Date) c.push(`Expires=${options.expires.toUTCString()}`);
|
|
114
|
+
if (options.httpOnly) c.push("HttpOnly");
|
|
115
|
+
if (typeof options.path === "string") c.push(`Path=${options.path}`);
|
|
116
|
+
const sameSite = resolveSameSite(options.sameSite);
|
|
117
|
+
if (sameSite) c.push(`SameSite=${sameSite}`);
|
|
118
|
+
if (options.secure) c.push("Secure");
|
|
119
|
+
return c.join("; ");
|
|
120
|
+
};
|
|
103
121
|
function tryDecodeUriComponent(str) {
|
|
104
122
|
try {
|
|
105
123
|
return decodeURIComponent(str);
|
|
@@ -123,20 +141,6 @@ function resolveSameSite(sameSite) {
|
|
|
123
141
|
if (sameSite === false) return "None";
|
|
124
142
|
if (sameSite) return SAMESITE[sameSite];
|
|
125
143
|
}
|
|
126
|
-
var createSetCookieValue = (cookieName, cookieValue, options) => {
|
|
127
|
-
const c = [`${cookieName}=${cookieValue}`];
|
|
128
|
-
if (typeof options.domain === "string") c.push(`Domain=${options.domain}`);
|
|
129
|
-
if (typeof options.maxAge === "number") c.push(`Max-Age=${options.maxAge}`);
|
|
130
|
-
else if (Array.isArray(options.maxAge)) c.push(`Max-Age=${options.maxAge[0] * UNIT[options.maxAge[1]]}`);
|
|
131
|
-
else if (typeof options.expires === "number" || typeof options.expires == "string") c.push(`Expires=${options.expires}`);
|
|
132
|
-
else if (options.expires instanceof Date) c.push(`Expires=${options.expires.toUTCString()}`);
|
|
133
|
-
if (options.httpOnly) c.push("HttpOnly");
|
|
134
|
-
if (typeof options.path === "string") c.push(`Path=${options.path}`);
|
|
135
|
-
const sameSite = resolveSameSite(options.sameSite);
|
|
136
|
-
if (sameSite) c.push(`SameSite=${sameSite}`);
|
|
137
|
-
if (options.secure) c.push("Secure");
|
|
138
|
-
return c.join("; ");
|
|
139
|
-
};
|
|
140
144
|
var REQ_COOKIE = Symbol("request-cookies");
|
|
141
145
|
var RES_COOKIE = Symbol("response-cookies");
|
|
142
146
|
var LIVE_COOKIE = Symbol("live-cookies");
|
|
@@ -192,7 +196,8 @@ var Cookie = class {
|
|
|
192
196
|
return Object.values(this[RES_COOKIE]);
|
|
193
197
|
}
|
|
194
198
|
};
|
|
195
|
-
/** @public */
|
|
199
|
+
/** @public */
|
|
200
|
+
var mergeHeadersCookies = (headers, cookies) => {
|
|
196
201
|
const cookieHeaders = cookies.headers();
|
|
197
202
|
if (cookieHeaders.length > 0) {
|
|
198
203
|
const newHeaders = new Headers(headers);
|
|
@@ -201,12 +206,15 @@ var Cookie = class {
|
|
|
201
206
|
}
|
|
202
207
|
return headers;
|
|
203
208
|
};
|
|
204
|
-
/** @public */
|
|
209
|
+
/** @public */
|
|
210
|
+
var RewriteMessage = class extends AbortMessage {
|
|
205
211
|
pathname;
|
|
206
212
|
constructor(pathname) {
|
|
207
|
-
super()
|
|
213
|
+
super();
|
|
214
|
+
this.pathname = pathname;
|
|
208
215
|
}
|
|
209
216
|
};
|
|
217
|
+
shareClassIdentity(RewriteMessage, "RewriteMessage");
|
|
210
218
|
var encoder = /*#__PURE__*/ new TextEncoder();
|
|
211
219
|
function getContentType(headers) {
|
|
212
220
|
return (headers.get("content-type")?.split(/[;,]/, 1)[0].trim() ?? "").toLowerCase();
|
|
@@ -225,108 +233,9 @@ var RequestEvSharedNonce = "@nonce";
|
|
|
225
233
|
var RequestEvIsRewrite = "@rewrite";
|
|
226
234
|
var RequestEvShareServerTiming = "@serverTiming";
|
|
227
235
|
var RequestEvETagCacheKey = "@eTagCacheKey";
|
|
228
|
-
var
|
|
236
|
+
var RequestEvCaughtError = "@caughtError";
|
|
229
237
|
var RequestEvHttpStatusMessage = "@httpStatusMessage";
|
|
230
|
-
function
|
|
231
|
-
return requestEv[RequestEvRoute];
|
|
232
|
-
}
|
|
233
|
-
function getRequestMode(requestEv) {
|
|
234
|
-
return requestEv[RequestEvMode];
|
|
235
|
-
}
|
|
236
|
-
var ABORT_INDEX = Number.MAX_SAFE_INTEGER;
|
|
237
|
-
var isDangerousKey = (k) => k === "__proto__" || k === "constructor" || k === "prototype";
|
|
238
|
-
var isArrayIndexKey = (k) => /^(0|[1-9]\d*)$/.test(k);
|
|
239
|
-
var createFormPathNode = () => ({
|
|
240
|
-
children: /* @__PURE__ */ new Map(),
|
|
241
|
-
isArray: true
|
|
242
|
-
});
|
|
243
|
-
var getFormPathTree = (formData) => {
|
|
244
|
-
const root = createFormPathNode();
|
|
245
|
-
for (const [name] of formData) {
|
|
246
|
-
const keys = name.split(".");
|
|
247
|
-
let hasDangerousKey = false;
|
|
248
|
-
for (const key of keys) if (isDangerousKey(key)) {
|
|
249
|
-
hasDangerousKey = true;
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
if (hasDangerousKey) continue;
|
|
253
|
-
let pathNode = root;
|
|
254
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
255
|
-
const key = keys[i];
|
|
256
|
-
if (key.endsWith("[]")) break;
|
|
257
|
-
let childNode = pathNode.children.get(key);
|
|
258
|
-
if (!childNode) {
|
|
259
|
-
childNode = createFormPathNode();
|
|
260
|
-
pathNode.children.set(key, childNode);
|
|
261
|
-
}
|
|
262
|
-
if (!isArrayIndexKey(keys[i + 1])) childNode.isArray = false;
|
|
263
|
-
pathNode = childNode;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
return root;
|
|
267
|
-
};
|
|
268
|
-
var formToObj = (formData) => {
|
|
269
|
-
/**
|
|
270
|
-
* Convert FormData to object Handle nested form input using dot notation Handle array input using
|
|
271
|
-
* indexed dot notation (name.0, name.0) or bracket notation (name[]), the later is needed for
|
|
272
|
-
* multiselects Create values object by form data entries
|
|
273
|
-
*/ const values = Object.create(null);
|
|
274
|
-
const pathTree = getFormPathTree(formData);
|
|
275
|
-
for (const [name, value] of formData) {
|
|
276
|
-
const keys = name.split(".");
|
|
277
|
-
let hasDangerousKey = false;
|
|
278
|
-
for (let i = 0; i < keys.length; i++) if (isDangerousKey(keys[i])) {
|
|
279
|
-
hasDangerousKey = true;
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
if (hasDangerousKey) continue;
|
|
283
|
-
let object = values;
|
|
284
|
-
let pathNode = pathTree;
|
|
285
|
-
for (let i = 0; i < keys.length; i++) {
|
|
286
|
-
const key = keys[i];
|
|
287
|
-
if (key.endsWith("[]")) {
|
|
288
|
-
const arrayKey = key.slice(0, -2);
|
|
289
|
-
if (isDangerousKey(arrayKey)) break;
|
|
290
|
-
const existingValue = object[arrayKey];
|
|
291
|
-
if (existingValue !== void 0 && !Array.isArray(existingValue)) break;
|
|
292
|
-
object[arrayKey] = existingValue || [];
|
|
293
|
-
object[arrayKey].push(value);
|
|
294
|
-
break;
|
|
295
|
-
}
|
|
296
|
-
if (Array.isArray(object) && !isArrayIndexKey(key)) break;
|
|
297
|
-
if (i < keys.length - 1) {
|
|
298
|
-
const childNode = pathNode.children.get(key);
|
|
299
|
-
const nextValue = object[key];
|
|
300
|
-
if (nextValue !== void 0) {
|
|
301
|
-
object = nextValue;
|
|
302
|
-
pathNode = childNode;
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
object = object[key] = childNode.isArray ? [] : Object.create(null);
|
|
306
|
-
pathNode = childNode;
|
|
307
|
-
} else object[key] = value;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return values;
|
|
311
|
-
};
|
|
312
|
-
var parseRequest = async ({ request, method, query }, sharedMap) => {
|
|
313
|
-
const type = getContentType(request.headers);
|
|
314
|
-
if (type === "application/x-www-form-urlencoded" || type === "multipart/form-data") {
|
|
315
|
-
const formData = await request.formData();
|
|
316
|
-
sharedMap.set(RequestEvSharedActionFormData, formData);
|
|
317
|
-
return formToObj(formData);
|
|
318
|
-
} else if (type === "application/json") return await request.json();
|
|
319
|
-
else if (type === "application/qwik-json") {
|
|
320
|
-
if (method === "GET" && query.has("qdata")) {
|
|
321
|
-
const data = query.get(QDATA_KEY);
|
|
322
|
-
if (data) try {
|
|
323
|
-
return await _deserialize(decodeURIComponent(data));
|
|
324
|
-
} catch {}
|
|
325
|
-
}
|
|
326
|
-
return await _deserialize(await request.text());
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolved) {
|
|
238
|
+
function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolved, routerConfig) {
|
|
330
239
|
const { request, platform, env } = serverRequestEv;
|
|
331
240
|
const sharedMap = /* @__PURE__ */ new Map();
|
|
332
241
|
const cookie = new Cookie(request.headers.get("cookie"));
|
|
@@ -404,6 +313,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
|
|
|
404
313
|
};
|
|
405
314
|
const requestEv = {
|
|
406
315
|
[RequestEvMode]: serverRequestEv.mode,
|
|
316
|
+
[RequestEvRouterConfig]: routerConfig,
|
|
407
317
|
get [RequestEvRoute]() {
|
|
408
318
|
return loadedRoute;
|
|
409
319
|
},
|
|
@@ -444,13 +354,13 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
|
|
|
444
354
|
check();
|
|
445
355
|
headers.set(target, createCacheControl(cacheControl));
|
|
446
356
|
},
|
|
447
|
-
resolveValue: async (loaderOrAction) => {
|
|
357
|
+
resolveValue: (async (loaderOrAction) => {
|
|
448
358
|
if (loaderOrAction.__brand === "server_loader") {
|
|
449
359
|
const loaderValues = getRouteLoaderValues(requestEv);
|
|
450
360
|
if (loaderOrAction.__id in loaderValues) return loaderValues[loaderOrAction.__id];
|
|
451
361
|
return loadRouteLoader(loaderOrAction, requestEv);
|
|
452
362
|
}
|
|
453
|
-
},
|
|
363
|
+
}),
|
|
454
364
|
status: (statusCode) => {
|
|
455
365
|
if (typeof statusCode === "number") {
|
|
456
366
|
check();
|
|
@@ -472,8 +382,8 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
|
|
|
472
382
|
check();
|
|
473
383
|
status = statusCode;
|
|
474
384
|
if (url) {
|
|
475
|
-
if (
|
|
476
|
-
const fixedURL = url.replace(
|
|
385
|
+
if (/^[/\\]{2,}/.test(url) || /([^:])[/\\]{2,}/.test(url)) {
|
|
386
|
+
const fixedURL = url.replace(/^[/\\]{2,}/, "/").replace(/([^:])[/\\]{2,}/g, "$1/");
|
|
477
387
|
console.warn(`Redirect URL ${url} is invalid, fixing to ${fixedURL}`);
|
|
478
388
|
url = fixedURL;
|
|
479
389
|
}
|
|
@@ -535,6 +445,107 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
|
|
|
535
445
|
};
|
|
536
446
|
return requestEv;
|
|
537
447
|
}
|
|
448
|
+
function getRequestRoute(requestEv) {
|
|
449
|
+
return requestEv[RequestEvRoute];
|
|
450
|
+
}
|
|
451
|
+
function getRequestMode(requestEv) {
|
|
452
|
+
return requestEv[RequestEvMode];
|
|
453
|
+
}
|
|
454
|
+
var ABORT_INDEX = Number.MAX_SAFE_INTEGER;
|
|
455
|
+
var parseRequest = async ({ request, method, query }, sharedMap) => {
|
|
456
|
+
const type = getContentType(request.headers);
|
|
457
|
+
if (type === "application/x-www-form-urlencoded" || type === "multipart/form-data") {
|
|
458
|
+
const formData = await request.formData();
|
|
459
|
+
sharedMap.set(RequestEvSharedActionFormData, formData);
|
|
460
|
+
return formToObj(formData);
|
|
461
|
+
} else if (type === "application/json") return await request.json();
|
|
462
|
+
else if (type === "application/qwik-json") {
|
|
463
|
+
if (method === "GET" && query.has("qdata")) {
|
|
464
|
+
const data = query.get(QDATA_KEY);
|
|
465
|
+
if (data) try {
|
|
466
|
+
return await _deserialize(decodeURIComponent(data));
|
|
467
|
+
} catch {}
|
|
468
|
+
}
|
|
469
|
+
return await _deserialize(await request.text());
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
var isDangerousKey = (k) => k === "__proto__" || k === "constructor" || k === "prototype";
|
|
473
|
+
var MAX_FORM_ARRAY_LENGTH = 1e4;
|
|
474
|
+
var isArrayIndexKey = (k) => /^(0|[1-9]\d*)$/.test(k) && Number(k) < MAX_FORM_ARRAY_LENGTH;
|
|
475
|
+
var createFormPathNode = () => ({
|
|
476
|
+
children: /* @__PURE__ */ new Map(),
|
|
477
|
+
isArray: true
|
|
478
|
+
});
|
|
479
|
+
var getFormPathTree = (formData) => {
|
|
480
|
+
const root = createFormPathNode();
|
|
481
|
+
for (const [name] of formData) {
|
|
482
|
+
const keys = name.split(".");
|
|
483
|
+
let hasDangerousKey = false;
|
|
484
|
+
for (const key of keys) if (isDangerousKey(key)) {
|
|
485
|
+
hasDangerousKey = true;
|
|
486
|
+
break;
|
|
487
|
+
}
|
|
488
|
+
if (hasDangerousKey) continue;
|
|
489
|
+
let pathNode = root;
|
|
490
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
491
|
+
const key = keys[i];
|
|
492
|
+
if (key.endsWith("[]")) break;
|
|
493
|
+
let childNode = pathNode.children.get(key);
|
|
494
|
+
if (!childNode) {
|
|
495
|
+
childNode = createFormPathNode();
|
|
496
|
+
pathNode.children.set(key, childNode);
|
|
497
|
+
}
|
|
498
|
+
if (!isArrayIndexKey(keys[i + 1])) childNode.isArray = false;
|
|
499
|
+
pathNode = childNode;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return root;
|
|
503
|
+
};
|
|
504
|
+
var formToObj = (formData) => {
|
|
505
|
+
/**
|
|
506
|
+
* Convert FormData to object Handle nested form input using dot notation Handle array input using
|
|
507
|
+
* indexed dot notation (name.0, name.0) or bracket notation (name[]), the later is needed for
|
|
508
|
+
* multiselects Create values object by form data entries
|
|
509
|
+
*/
|
|
510
|
+
const values = Object.create(null);
|
|
511
|
+
const pathTree = getFormPathTree(formData);
|
|
512
|
+
for (const [name, value] of formData) {
|
|
513
|
+
const keys = name.split(".");
|
|
514
|
+
let hasDangerousKey = false;
|
|
515
|
+
for (let i = 0; i < keys.length; i++) if (isDangerousKey(keys[i])) {
|
|
516
|
+
hasDangerousKey = true;
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
if (hasDangerousKey) continue;
|
|
520
|
+
let object = values;
|
|
521
|
+
let pathNode = pathTree;
|
|
522
|
+
for (let i = 0; i < keys.length; i++) {
|
|
523
|
+
const key = keys[i];
|
|
524
|
+
if (key.endsWith("[]")) {
|
|
525
|
+
const arrayKey = key.slice(0, -2);
|
|
526
|
+
if (isDangerousKey(arrayKey)) break;
|
|
527
|
+
const existingValue = object[arrayKey];
|
|
528
|
+
if (existingValue !== void 0 && !Array.isArray(existingValue)) break;
|
|
529
|
+
object[arrayKey] = existingValue || [];
|
|
530
|
+
object[arrayKey].push(value);
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
if (Array.isArray(object) && !isArrayIndexKey(key)) break;
|
|
534
|
+
if (i < keys.length - 1) {
|
|
535
|
+
const childNode = pathNode.children.get(key);
|
|
536
|
+
const nextValue = object[key];
|
|
537
|
+
if (nextValue !== void 0) {
|
|
538
|
+
object = nextValue;
|
|
539
|
+
pathNode = childNode;
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
object = object[key] = childNode.isArray ? [] : Object.create(null);
|
|
543
|
+
pathNode = childNode;
|
|
544
|
+
} else object[key] = value;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return values;
|
|
548
|
+
};
|
|
538
549
|
var MAX_CACHE_SIZE = typeof globalThis.__SSR_CACHE_SIZE__ === "number" ? globalThis.__SSR_CACHE_SIZE__ : 50;
|
|
539
550
|
function createLruCache() {
|
|
540
551
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -566,7 +577,8 @@ var loaderCache = createLruCache();
|
|
|
566
577
|
/**
|
|
567
578
|
* Resolve an eTag value from a ContentModuleETag (string, function, or undefined). Returns the eTag
|
|
568
579
|
* string or null.
|
|
569
|
-
*/
|
|
580
|
+
*/
|
|
581
|
+
function resolveETag(eTagExport, headProps) {
|
|
570
582
|
if (eTagExport === void 0) return null;
|
|
571
583
|
if (typeof eTagExport === "function") return eTagExport(headProps);
|
|
572
584
|
return eTagExport;
|
|
@@ -574,31 +586,38 @@ var loaderCache = createLruCache();
|
|
|
574
586
|
/**
|
|
575
587
|
* Resolve a cache key from a CacheKeyFn. The default key callback is only called when `cacheKey ===
|
|
576
588
|
* true`.
|
|
577
|
-
*/
|
|
589
|
+
*/
|
|
590
|
+
function resolveCacheKey(cacheKeyExport, defaultKey, requestEv, eTag) {
|
|
578
591
|
if (cacheKeyExport === true) return defaultKey(requestEv, eTag);
|
|
579
592
|
if (typeof cacheKeyExport !== "function") return "";
|
|
580
593
|
return cacheKeyExport(requestEv, eTag) || "";
|
|
581
594
|
}
|
|
582
|
-
/** Build the default SSR cache key. eTag slot is dropped when no eTag was resolved. */
|
|
595
|
+
/** Build the default SSR cache key. eTag slot is dropped when no eTag was resolved. */
|
|
596
|
+
function defaultSsrCacheKey(requestEv, eTag) {
|
|
583
597
|
const status = requestEv.status();
|
|
584
|
-
const pathname = requestEv.
|
|
598
|
+
const pathname = requestEv.originalUrl.pathname;
|
|
585
599
|
return eTag ? `${status}|${eTag}|${pathname}` : `${status}|${pathname}`;
|
|
586
600
|
}
|
|
587
|
-
/** Build the default loader cache key. eTag slot is dropped when no eTag was resolved. */
|
|
601
|
+
/** Build the default loader cache key. eTag slot is dropped when no eTag was resolved. */
|
|
602
|
+
function defaultLoaderCacheKey(requestEv, eTag) {
|
|
588
603
|
const loaderId = requestEv.sharedMap.get(QLoaderId);
|
|
589
604
|
const base = `${requestEv.url.pathname}|${requestEv.url.search}|${loaderId}`;
|
|
590
605
|
return eTag ? `${base}|${eTag}` : base;
|
|
591
606
|
}
|
|
592
|
-
/** Get a cached SSR entry by key (LRU touch). */
|
|
607
|
+
/** Get a cached SSR entry by key (LRU touch). */
|
|
608
|
+
function getCachedSsr(key) {
|
|
593
609
|
return ssrCache.get(key);
|
|
594
610
|
}
|
|
595
|
-
/** Cache an SSR entry by key, evicting the least recently used entry if at capacity. */
|
|
611
|
+
/** Cache an SSR entry by key, evicting the least recently used entry if at capacity. */
|
|
612
|
+
function setCachedSsr(key, entry) {
|
|
596
613
|
ssrCache.set(key, entry);
|
|
597
614
|
}
|
|
598
|
-
/** Get a cached loader entry by key (LRU touch). */
|
|
615
|
+
/** Get a cached loader entry by key (LRU touch). */
|
|
616
|
+
function getCachedLoader(key) {
|
|
599
617
|
return loaderCache.get(key);
|
|
600
618
|
}
|
|
601
|
-
/** Cache a loader entry by key, evicting the least recently used entry if at capacity. */
|
|
619
|
+
/** Cache a loader entry by key, evicting the least recently used entry if at capacity. */
|
|
620
|
+
function setCachedLoader(key, entry) {
|
|
602
621
|
loaderCache.set(key, entry);
|
|
603
622
|
}
|
|
604
623
|
/**
|
|
@@ -608,7 +627,8 @@ var loaderCache = createLruCache();
|
|
|
608
627
|
* cleared.
|
|
609
628
|
*
|
|
610
629
|
* @public
|
|
611
|
-
*/
|
|
630
|
+
*/
|
|
631
|
+
function clearSsrCache(cacheKey) {
|
|
612
632
|
ssrCache.clear(cacheKey);
|
|
613
633
|
}
|
|
614
634
|
/**
|
|
@@ -618,59 +638,25 @@ var loaderCache = createLruCache();
|
|
|
618
638
|
* cleared.
|
|
619
639
|
*
|
|
620
640
|
* @public
|
|
621
|
-
*/
|
|
641
|
+
*/
|
|
642
|
+
function clearLoaderCache(cacheKey) {
|
|
622
643
|
loaderCache.clear(cacheKey);
|
|
623
644
|
}
|
|
624
645
|
/**
|
|
625
646
|
* Create per-loader request event views. Loader-specific URL/search data is scoped to the view,
|
|
626
647
|
* while request-wide state (headers, cookies, loader value maps, etc.) still delegates to the
|
|
627
648
|
* original request event.
|
|
628
|
-
*/
|
|
649
|
+
*/
|
|
650
|
+
function createLoaderRequestEventFactory(requestEv) {
|
|
629
651
|
return (loader) => getLoaderRequestEvent(loader, requestEv);
|
|
630
652
|
}
|
|
631
653
|
/**
|
|
632
|
-
* Resolve the loader's cacheControl option. Loaders default to `no-cache` so the browser always
|
|
633
|
-
* revalidates; pair with `eTag` for cheap 304s. A function form may return `null` to skip the
|
|
634
|
-
* header entirely.
|
|
635
|
-
*/ function resolveLoaderCacheControl(option, requestEv) {
|
|
636
|
-
const value = typeof option === "function" ? option(requestEv) : option;
|
|
637
|
-
return value === void 0 ? "no-cache" : value;
|
|
638
|
-
}
|
|
639
|
-
async function runBlockingLoadersBeforeTarget(routeLoaders, targetLoader, requestEv) {
|
|
640
|
-
for (const loader of routeLoaders) {
|
|
641
|
-
if (loader === targetLoader) return;
|
|
642
|
-
if (loader.__blockSSR) await loadRouteLoader(loader, requestEv);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
function setLoaderData(requestEv, routeLoaders, loaderPaths) {
|
|
646
|
-
if (loaderPaths) Object.assign(getRouteLoaderCtx(requestEv).loaderPaths, loaderPaths);
|
|
647
|
-
setRouteLoaders(requestEv, routeLoaders);
|
|
648
|
-
}
|
|
649
|
-
/** Resolve eTag from a static string or function (before running the loader). */ function resolvePreETag(eTagOption, requestEv) {
|
|
650
|
-
if (typeof eTagOption === "string") return normalizeETag(eTagOption);
|
|
651
|
-
const result = eTagOption(requestEv);
|
|
652
|
-
return result ? normalizeETag(result) : "";
|
|
653
|
-
}
|
|
654
|
-
function addVaryHeader(requestEv, value) {
|
|
655
|
-
const vary = requestEv.headers.get("Vary");
|
|
656
|
-
if (!vary) {
|
|
657
|
-
requestEv.headers.set("Vary", value);
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
if (!vary.split(",").map((item) => item.trim().toLowerCase()).includes(value.toLowerCase())) requestEv.headers.set("Vary", `${vary}, ${value}`);
|
|
661
|
-
}
|
|
662
|
-
async function sendLoaderResponse(requestEv, data, cacheControl) {
|
|
663
|
-
requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
|
|
664
|
-
addVaryHeader(requestEv, FULLPATH_HEADER);
|
|
665
|
-
if (cacheControl !== null && !requestEv.headers.has("Cache-Control")) requestEv.cacheControl(cacheControl);
|
|
666
|
-
requestEv.send(200, data);
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
654
|
* Handler that executes the requested loader and returns the result as JSON. Runs AFTER
|
|
670
655
|
* plugin/route middleware, so middleware redirects/errors are handled by `jsonRequestWrapper`. The
|
|
671
656
|
* loader function's own redirects/errors are caught by getRouteLoaderResponse and serialized in the
|
|
672
657
|
* LoaderResponse envelope ({ d, r, e }).
|
|
673
|
-
*/
|
|
658
|
+
*/
|
|
659
|
+
function loaderHandler(routeLoaders, loaderPaths) {
|
|
674
660
|
return async (requestEvent) => {
|
|
675
661
|
const requestEv = requestEvent;
|
|
676
662
|
if (!requestEv.sharedMap.has("@isQLoader")) return;
|
|
@@ -685,15 +671,18 @@ async function sendLoaderResponse(requestEv, data, cacheControl) {
|
|
|
685
671
|
await runBlockingLoadersBeforeTarget(routeLoaders, loader, requestEv);
|
|
686
672
|
const loaderRequestEv = createLoaderRequestEventFactory(requestEv)(loader);
|
|
687
673
|
const cacheControl = resolveLoaderCacheControl(loader.__cacheControl, loaderRequestEv);
|
|
674
|
+
const applyCacheControl = () => {
|
|
675
|
+
if (cacheControl !== null && !requestEv.headers.has("Cache-Control")) requestEv.cacheControl(cacheControl);
|
|
676
|
+
};
|
|
688
677
|
const normalizedETag = loader.__eTag !== void 0 ? resolvePreETag(loader.__eTag, loaderRequestEv) : "";
|
|
689
|
-
if (normalizedETag && performETagMatch(loaderRequestEv, normalizedETag)) return;
|
|
678
|
+
if (normalizedETag && performETagMatch(loaderRequestEv, normalizedETag, applyCacheControl)) return;
|
|
690
679
|
let cacheKey = "";
|
|
691
680
|
if (loader.__cacheKey) cacheKey = resolveCacheKey(loader.__cacheKey, defaultLoaderCacheKey, loaderRequestEv, normalizedETag);
|
|
692
681
|
if (cacheKey) {
|
|
693
682
|
const cached = getCachedLoader(cacheKey);
|
|
694
683
|
if (cached) {
|
|
695
684
|
if (!normalizedETag) {
|
|
696
|
-
if (performETagMatch(loaderRequestEv, cached.eTag)) return;
|
|
685
|
+
if (performETagMatch(loaderRequestEv, cached.eTag, applyCacheControl)) return;
|
|
697
686
|
} else setETagHeader(loaderRequestEv, cached.eTag);
|
|
698
687
|
await sendLoaderResponse(requestEv, cached.body, cacheControl);
|
|
699
688
|
return;
|
|
@@ -708,13 +697,53 @@ async function sendLoaderResponse(requestEv, data, cacheControl) {
|
|
|
708
697
|
eTag: finalETag,
|
|
709
698
|
body: data
|
|
710
699
|
});
|
|
711
|
-
if (!normalizedETag && finalETag && performETagMatch(loaderRequestEv, finalETag)) return;
|
|
700
|
+
if (!normalizedETag && finalETag && performETagMatch(loaderRequestEv, finalETag, applyCacheControl)) return;
|
|
712
701
|
await sendLoaderResponse(requestEv, data, cacheControl);
|
|
713
702
|
};
|
|
714
703
|
}
|
|
715
|
-
/**
|
|
704
|
+
/**
|
|
705
|
+
* Resolve the loader's cacheControl option. Loaders default to private revalidation; pair with
|
|
706
|
+
* `eTag` for cheap 304s. A function form may return `null` to skip the header entirely.
|
|
707
|
+
*/
|
|
708
|
+
function resolveLoaderCacheControl(option, requestEv) {
|
|
709
|
+
const value = typeof option === "function" ? option(requestEv) : option;
|
|
710
|
+
return value === void 0 ? "private" : value;
|
|
711
|
+
}
|
|
712
|
+
async function runBlockingLoadersBeforeTarget(routeLoaders, targetLoader, requestEv) {
|
|
713
|
+
for (const loader of routeLoaders) {
|
|
714
|
+
if (loader === targetLoader) return;
|
|
715
|
+
if (loader.__blockSSR) await loadRouteLoader(loader, requestEv);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
function setLoaderData(requestEv, routeLoaders, loaderPaths) {
|
|
719
|
+
if (loaderPaths) Object.assign(getRouteLoaderCtx(requestEv).loaderPaths, loaderPaths);
|
|
720
|
+
setRouteLoaders(requestEv, routeLoaders);
|
|
721
|
+
}
|
|
722
|
+
/** Resolve eTag from a static string or function (before running the loader). */
|
|
723
|
+
function resolvePreETag(eTagOption, requestEv) {
|
|
724
|
+
if (typeof eTagOption === "string") return normalizeETag(eTagOption);
|
|
725
|
+
const result = eTagOption(requestEv);
|
|
726
|
+
return result ? normalizeETag(result) : "";
|
|
727
|
+
}
|
|
728
|
+
async function sendLoaderResponse(requestEv, data, cacheControl) {
|
|
729
|
+
requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
|
|
730
|
+
addVaryHeader(requestEv, FULLPATH_HEADER);
|
|
731
|
+
if (cacheControl !== null && !requestEv.headers.has("Cache-Control")) requestEv.cacheControl(cacheControl);
|
|
732
|
+
requestEv.send(200, data);
|
|
733
|
+
}
|
|
734
|
+
function addVaryHeader(requestEv, value) {
|
|
735
|
+
const vary = requestEv.headers.get("Vary");
|
|
736
|
+
if (!vary) {
|
|
737
|
+
requestEv.headers.set("Vary", value);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
if (!vary.split(",").map((item) => item.trim().toLowerCase()).includes(value.toLowerCase())) requestEv.headers.set("Vary", `${vary}, ${value}`);
|
|
741
|
+
}
|
|
742
|
+
/** Serialize and send a JSON response (used by error/redirect paths in jsonRequestWrapper). */
|
|
743
|
+
async function sendJsonResponse(requestEv, responseData, status = 200) {
|
|
716
744
|
const data = await _serialize(responseData);
|
|
717
745
|
requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
|
|
746
|
+
if (!requestEv.headers.has("Cache-Control")) requestEv.cacheControl("private");
|
|
718
747
|
requestEv.send(status, data);
|
|
719
748
|
}
|
|
720
749
|
async function sendActionResponse(requestEv, responseData) {
|
|
@@ -731,7 +760,8 @@ async function sendActionResponse(requestEv, responseData) {
|
|
|
731
760
|
* By calling `await next()` inside a try/catch, middleware redirects and errors are captured and
|
|
732
761
|
* returned as JSON envelopes instead of HTTP redirects/error pages. This keeps SPA navigation
|
|
733
762
|
* intact on the client.
|
|
734
|
-
*/
|
|
763
|
+
*/
|
|
764
|
+
function jsonRequestWrapper() {
|
|
735
765
|
return async (requestEvent) => {
|
|
736
766
|
const requestEv = requestEvent;
|
|
737
767
|
const isLoader = requestEv.internalRequest === "loader";
|
|
@@ -771,38 +801,6 @@ async function sendActionResponse(requestEv, responseData) {
|
|
|
771
801
|
}
|
|
772
802
|
};
|
|
773
803
|
}
|
|
774
|
-
function verifySerializable$1(data, qrl) {
|
|
775
|
-
try {
|
|
776
|
-
_verifySerializable(data, void 0);
|
|
777
|
-
} catch (e) {
|
|
778
|
-
if (e instanceof Error && qrl.dev) e.loc = qrl.dev;
|
|
779
|
-
throw e;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
async function measure$1(requestEv, name, fn) {
|
|
783
|
-
const start = performance.now();
|
|
784
|
-
try {
|
|
785
|
-
return await fn();
|
|
786
|
-
} finally {
|
|
787
|
-
const duration = performance.now() - start;
|
|
788
|
-
let measurements = requestEv.sharedMap.get("@serverTiming");
|
|
789
|
-
if (!measurements) requestEv.sharedMap.set("@serverTiming", measurements = []);
|
|
790
|
-
measurements.push([name, duration]);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
async function runValidators(requestEv, validators, data, devMode) {
|
|
794
|
-
let lastResult = {
|
|
795
|
-
success: true,
|
|
796
|
-
data
|
|
797
|
-
};
|
|
798
|
-
if (validators) for (const validator of validators) {
|
|
799
|
-
if (devMode) lastResult = await measure$1(requestEv, `validator$`, () => validator.validate(requestEv, data));
|
|
800
|
-
else lastResult = await validator.validate(requestEv, data);
|
|
801
|
-
if (!lastResult.success) return lastResult;
|
|
802
|
-
else data = lastResult.data;
|
|
803
|
-
}
|
|
804
|
-
return lastResult;
|
|
805
|
-
}
|
|
806
804
|
/**
|
|
807
805
|
* Handler for action requests (`?qaction={actionId}`).
|
|
808
806
|
*
|
|
@@ -812,7 +810,8 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
812
810
|
* If the action has no `invalidate` list, the client invalidates all current route loaders unless
|
|
813
811
|
* strict loaders mode treats it as `invalidate: []`. If `invalidate` is specified, only those
|
|
814
812
|
* loader hashes are sent for the client to re-fetch.
|
|
815
|
-
*/
|
|
813
|
+
*/
|
|
814
|
+
function actionHandler(routeActions) {
|
|
816
815
|
return async (requestEvent) => {
|
|
817
816
|
const requestEv = requestEvent;
|
|
818
817
|
if (!requestEv.sharedMap.has("@isQAction")) return;
|
|
@@ -852,10 +851,43 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
852
851
|
requestEv.send(requestEv.status(), serialized);
|
|
853
852
|
};
|
|
854
853
|
}
|
|
854
|
+
async function runValidators(requestEv, validators, data, devMode) {
|
|
855
|
+
let lastResult = {
|
|
856
|
+
success: true,
|
|
857
|
+
data
|
|
858
|
+
};
|
|
859
|
+
if (validators) for (const validator of validators) {
|
|
860
|
+
if (devMode) lastResult = await measure$1(requestEv, `validator$`, () => validator.validate(requestEv, data));
|
|
861
|
+
else lastResult = await validator.validate(requestEv, data);
|
|
862
|
+
if (!lastResult.success) return lastResult;
|
|
863
|
+
else data = lastResult.data;
|
|
864
|
+
}
|
|
865
|
+
return lastResult;
|
|
866
|
+
}
|
|
867
|
+
function verifySerializable$1(data, qrl) {
|
|
868
|
+
try {
|
|
869
|
+
_verifySerializable(data, void 0);
|
|
870
|
+
} catch (e) {
|
|
871
|
+
if (e instanceof Error && qrl.dev) e.loc = qrl.dev;
|
|
872
|
+
throw e;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
async function measure$1(requestEv, name, fn) {
|
|
876
|
+
const start = performance.now();
|
|
877
|
+
try {
|
|
878
|
+
return await fn();
|
|
879
|
+
} finally {
|
|
880
|
+
const duration = performance.now() - start;
|
|
881
|
+
let measurements = requestEv.sharedMap.get("@serverTiming");
|
|
882
|
+
if (!measurements) requestEv.sharedMap.set("@serverTiming", measurements = []);
|
|
883
|
+
measurements.push([name, duration]);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
855
886
|
/**
|
|
856
887
|
* A set of static paths generated by the SSG, including loader json. Routes always have a trailing
|
|
857
888
|
* slash, short for `.../index.html`
|
|
858
|
-
*/
|
|
889
|
+
*/
|
|
890
|
+
var staticPaths = /* @__PURE__ */ new Set(["__QWIK_ROUTER_STATIC_PATHS_ARRAY__"]);
|
|
859
891
|
/**
|
|
860
892
|
* Check if the current pathname needs a redirect due to trailing slash mismatch. If we're not sure,
|
|
861
893
|
* we fall through.
|
|
@@ -864,7 +896,8 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
864
896
|
*
|
|
865
897
|
* @returns The canonical path with the correct trailing slash if a redirect is needed, otherwise
|
|
866
898
|
* `undefined`.
|
|
867
|
-
*/
|
|
899
|
+
*/
|
|
900
|
+
function getStaticPathRedirect(method, url) {
|
|
868
901
|
const { pathname, search } = url;
|
|
869
902
|
if (method.toUpperCase() !== "GET" || pathname === "/" || !pathname.startsWith("/") || pathname.startsWith("//")) return;
|
|
870
903
|
const hasTrailingSlash = pathname.endsWith("/");
|
|
@@ -877,12 +910,14 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
877
910
|
* Decide whether a given request path is a static path, for optimizing file access.
|
|
878
911
|
*
|
|
879
912
|
* @internal
|
|
880
|
-
*/
|
|
913
|
+
*/
|
|
914
|
+
function isStaticPath(method, url) {
|
|
881
915
|
method = method.toUpperCase();
|
|
882
916
|
if (method !== "GET" && method !== "HEAD") return false;
|
|
883
917
|
const p = url.pathname;
|
|
884
|
-
|
|
885
|
-
if (p.startsWith(
|
|
918
|
+
const basePathname = globalThis.__QWIK_ROUTER_BASE_PATHNAME__ || "/";
|
|
919
|
+
if (p.startsWith(basePathname + (globalThis.__QWIK_BUILD_DIR__ || "build") + "/")) return true;
|
|
920
|
+
if (p.startsWith(basePathname + (globalThis.__QWIK_ASSETS_DIR__ || "assets") + "/")) return true;
|
|
886
921
|
if (globalThis.__NO_TRAILING_SLASH__ && p !== "/") return !p.endsWith("/") && (staticPaths.has(p) || staticPaths.has(p + "/"));
|
|
887
922
|
return staticPaths.has(p);
|
|
888
923
|
}
|
|
@@ -890,7 +925,8 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
890
925
|
* Hypertext Transfer Protocol (HTTP) response status codes.
|
|
891
926
|
*
|
|
892
927
|
* @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}
|
|
893
|
-
*/
|
|
928
|
+
*/
|
|
929
|
+
var HttpStatus = /* @__PURE__ */ function(HttpStatus) {
|
|
894
930
|
/**
|
|
895
931
|
* The server has received the request headers and the client should proceed to send the request
|
|
896
932
|
* body (in the case of a request for which a body needs to be sent; for example, a POST request).
|
|
@@ -899,59 +935,74 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
899
935
|
* Expect: 100-continue as a header in its initial request and receive a 100 Continue status code
|
|
900
936
|
* in response before sending the body. The response 417 Expectation Failed indicates the request
|
|
901
937
|
* should not be continued.
|
|
902
|
-
*/
|
|
903
|
-
|
|
938
|
+
*/
|
|
939
|
+
HttpStatus[HttpStatus["Continue"] = 100] = "Continue";
|
|
940
|
+
/** The requester has asked the server to switch protocols and the server has agreed to do so. */
|
|
941
|
+
HttpStatus[HttpStatus["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
904
942
|
/**
|
|
905
943
|
* A WebDAV request may contain many sub-requests involving file operations, requiring a long time
|
|
906
944
|
* to complete the request. This code indicates that the server has received and is processing the
|
|
907
945
|
* request, but no response is available yet. This prevents the client from timing out and
|
|
908
946
|
* assuming the request was lost.
|
|
909
|
-
*/
|
|
947
|
+
*/
|
|
948
|
+
HttpStatus[HttpStatus["Processing"] = 102] = "Processing";
|
|
910
949
|
/**
|
|
911
950
|
* Standard response for successful HTTP requests. The actual response will depend on the request
|
|
912
951
|
* method used. In a GET request, the response will contain an entity corresponding to the
|
|
913
952
|
* requested resource. In a POST request, the response will contain an entity describing or
|
|
914
953
|
* containing the result of the action.
|
|
915
|
-
*/
|
|
916
|
-
|
|
954
|
+
*/
|
|
955
|
+
HttpStatus[HttpStatus["Ok"] = 200] = "Ok";
|
|
956
|
+
/** The request has been fulfilled, resulting in the creation of a new resource. */
|
|
957
|
+
HttpStatus[HttpStatus["Created"] = 201] = "Created";
|
|
917
958
|
/**
|
|
918
959
|
* The request has been accepted for processing, but the processing has not been completed. The
|
|
919
960
|
* request might or might not be eventually acted upon, and may be disallowed when processing
|
|
920
961
|
* occurs.
|
|
921
|
-
*/
|
|
962
|
+
*/
|
|
963
|
+
HttpStatus[HttpStatus["Accepted"] = 202] = "Accepted";
|
|
922
964
|
/**
|
|
923
965
|
* SINCE HTTP/1.1 The server is a transforming proxy that received a 200 OK from its origin, but
|
|
924
966
|
* is returning a modified version of the origin's response.
|
|
925
|
-
*/
|
|
926
|
-
|
|
967
|
+
*/
|
|
968
|
+
HttpStatus[HttpStatus["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
969
|
+
/** The server successfully processed the request and is not returning any content. */
|
|
970
|
+
HttpStatus[HttpStatus["NoContent"] = 204] = "NoContent";
|
|
927
971
|
/**
|
|
928
972
|
* The server successfully processed the request, but is not returning any content. Unlike a 204
|
|
929
973
|
* response, this response requires that the requester reset the document view.
|
|
930
|
-
*/
|
|
974
|
+
*/
|
|
975
|
+
HttpStatus[HttpStatus["ResetContent"] = 205] = "ResetContent";
|
|
931
976
|
/**
|
|
932
977
|
* The server is delivering only part of the resource (byte serving) due to a range header sent by
|
|
933
978
|
* the client. The range header is used by HTTP clients to enable resuming of interrupted
|
|
934
979
|
* downloads, or split a download into multiple simultaneous streams.
|
|
935
|
-
*/
|
|
980
|
+
*/
|
|
981
|
+
HttpStatus[HttpStatus["PartialContent"] = 206] = "PartialContent";
|
|
936
982
|
/**
|
|
937
983
|
* The message body that follows is an XML message and can contain a number of separate response
|
|
938
984
|
* codes, depending on how many sub-requests were made.
|
|
939
|
-
*/
|
|
985
|
+
*/
|
|
986
|
+
HttpStatus[HttpStatus["MultiStatus"] = 207] = "MultiStatus";
|
|
940
987
|
/**
|
|
941
988
|
* The members of a DAV binding have already been enumerated in a preceding part of the
|
|
942
989
|
* (multistatus) response, and are not being included again.
|
|
943
|
-
*/
|
|
990
|
+
*/
|
|
991
|
+
HttpStatus[HttpStatus["AlreadyReported"] = 208] = "AlreadyReported";
|
|
944
992
|
/**
|
|
945
993
|
* The server has fulfilled a request for the resource, and the response is a representation of
|
|
946
994
|
* the result of one or more instance-manipulations applied to the current instance.
|
|
947
|
-
*/
|
|
995
|
+
*/
|
|
996
|
+
HttpStatus[HttpStatus["ImUsed"] = 226] = "ImUsed";
|
|
948
997
|
/**
|
|
949
998
|
* Indicates multiple options for the resource from which the client may choose (via agent-driven
|
|
950
999
|
* content negotiation). For example, this code could be used to present multiple video format
|
|
951
1000
|
* options, to list files with different filename extensions, or to suggest word-sense
|
|
952
1001
|
* disambiguation.
|
|
953
|
-
*/
|
|
954
|
-
|
|
1002
|
+
*/
|
|
1003
|
+
HttpStatus[HttpStatus["MultipleChoices"] = 300] = "MultipleChoices";
|
|
1004
|
+
/** This and all future requests should be directed to the given URI. */
|
|
1005
|
+
HttpStatus[HttpStatus["MovedPermanently"] = 301] = "MovedPermanently";
|
|
955
1006
|
/**
|
|
956
1007
|
* This is an example of industry practice contradicting the standard. The HTTP/1.0 specification
|
|
957
1008
|
* (RFC 1945) required the client to perform a temporary redirect (the original describing phrase
|
|
@@ -959,78 +1010,95 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
959
1010
|
* See Other. Therefore, HTTP/1.1 added status codes 303 and 307 to distinguish between the two
|
|
960
1011
|
* behaviors. However, some Web applications and frameworks use the 302 status code as if it were
|
|
961
1012
|
* the 303.
|
|
962
|
-
*/
|
|
1013
|
+
*/
|
|
1014
|
+
HttpStatus[HttpStatus["Found"] = 302] = "Found";
|
|
963
1015
|
/**
|
|
964
1016
|
* SINCE HTTP/1.1 The response to the request can be found under another URI using a GET method.
|
|
965
1017
|
* When received in response to a POST (or PUT/DELETE), the client should presume that the server
|
|
966
1018
|
* has received the data and should issue a redirect with a separate GET message.
|
|
967
|
-
*/
|
|
1019
|
+
*/
|
|
1020
|
+
HttpStatus[HttpStatus["SeeOther"] = 303] = "SeeOther";
|
|
968
1021
|
/**
|
|
969
1022
|
* Indicates that the resource has not been modified since the version specified by the request
|
|
970
1023
|
* headers If-Modified-Since or If-None-Match. In such case, there is no need to retransmit the
|
|
971
1024
|
* resource since the client still has a previously-downloaded copy.
|
|
972
|
-
*/
|
|
1025
|
+
*/
|
|
1026
|
+
HttpStatus[HttpStatus["NotModified"] = 304] = "NotModified";
|
|
973
1027
|
/**
|
|
974
1028
|
* SINCE HTTP/1.1 The requested resource is available only through a proxy, the address for which
|
|
975
1029
|
* is provided in the response. Many HTTP clients (such as Mozilla and Internet Explorer) do not
|
|
976
1030
|
* correctly handle responses with this status code, primarily for security reasons.
|
|
977
|
-
*/
|
|
978
|
-
|
|
1031
|
+
*/
|
|
1032
|
+
HttpStatus[HttpStatus["UseProxy"] = 305] = "UseProxy";
|
|
1033
|
+
/** No longer used. Originally meant "Subsequent requests should use the specified proxy." */
|
|
1034
|
+
HttpStatus[HttpStatus["SwitchProxy"] = 306] = "SwitchProxy";
|
|
979
1035
|
/**
|
|
980
1036
|
* SINCE HTTP/1.1 In this case, the request should be repeated with another URI; however, future
|
|
981
1037
|
* requests should still use the original URI. In contrast to how 302 was historically
|
|
982
1038
|
* implemented, the request method is not allowed to be changed when reissuing the original
|
|
983
1039
|
* request. For example, a POST request should be repeated using another POST request.
|
|
984
|
-
*/
|
|
1040
|
+
*/
|
|
1041
|
+
HttpStatus[HttpStatus["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
985
1042
|
/**
|
|
986
1043
|
* The request and all future requests should be repeated using another URI. 307 and 308 parallel
|
|
987
1044
|
* the behaviors of 302 and 301, but do not allow the HTTP method to change. So, for example,
|
|
988
1045
|
* submitting a form to a permanently redirected resource may continue smoothly.
|
|
989
|
-
*/
|
|
1046
|
+
*/
|
|
1047
|
+
HttpStatus[HttpStatus["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
990
1048
|
/**
|
|
991
1049
|
* The server cannot or will not process the request due to an apparent client error (e.g.,
|
|
992
1050
|
* malformed request syntax, too large size, invalid request message framing, or deceptive request
|
|
993
1051
|
* routing).
|
|
994
|
-
*/
|
|
1052
|
+
*/
|
|
1053
|
+
HttpStatus[HttpStatus["BadRequest"] = 400] = "BadRequest";
|
|
995
1054
|
/**
|
|
996
1055
|
* Similar to 403 Forbidden, but specifically for use when authentication is required and has
|
|
997
1056
|
* failed or has not yet been provided. The response must include a WWW-Authenticate header field
|
|
998
1057
|
* containing a challenge applicable to the requested resource. See Basic access authentication
|
|
999
1058
|
* and Digest access authentication. 401 semantically means "unauthenticated",i.e. the user does
|
|
1000
1059
|
* not have the necessary credentials.
|
|
1001
|
-
*/
|
|
1060
|
+
*/
|
|
1061
|
+
HttpStatus[HttpStatus["Unauthorized"] = 401] = "Unauthorized";
|
|
1002
1062
|
/**
|
|
1003
1063
|
* Reserved for future use. The original intention was that this code might be used as part of
|
|
1004
1064
|
* some form of digital cash or micro payment scheme, but that has not happened, and this code is
|
|
1005
1065
|
* not usually used. Google Developers API uses this status if a particular developer has exceeded
|
|
1006
1066
|
* the daily limit on requests.
|
|
1007
|
-
*/
|
|
1067
|
+
*/
|
|
1068
|
+
HttpStatus[HttpStatus["PaymentRequired"] = 402] = "PaymentRequired";
|
|
1008
1069
|
/**
|
|
1009
1070
|
* The request was valid, but the server is refusing action. The user might not have the necessary
|
|
1010
1071
|
* permissions for a resource.
|
|
1011
|
-
*/
|
|
1072
|
+
*/
|
|
1073
|
+
HttpStatus[HttpStatus["Forbidden"] = 403] = "Forbidden";
|
|
1012
1074
|
/**
|
|
1013
1075
|
* The requested resource could not be found but may be available in the future. Subsequent
|
|
1014
1076
|
* requests by the client are permissible.
|
|
1015
|
-
*/
|
|
1077
|
+
*/
|
|
1078
|
+
HttpStatus[HttpStatus["NotFound"] = 404] = "NotFound";
|
|
1016
1079
|
/**
|
|
1017
1080
|
* A request method is not supported for the requested resource; for example, a GET request on a
|
|
1018
1081
|
* form that requires data to be presented via POST, or a PUT request on a read-only resource.
|
|
1019
|
-
*/
|
|
1082
|
+
*/
|
|
1083
|
+
HttpStatus[HttpStatus["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
1020
1084
|
/**
|
|
1021
1085
|
* The requested resource is capable of generating only content not acceptable according to the
|
|
1022
1086
|
* Accept headers sent in the request.
|
|
1023
|
-
*/
|
|
1024
|
-
|
|
1087
|
+
*/
|
|
1088
|
+
HttpStatus[HttpStatus["NotAcceptable"] = 406] = "NotAcceptable";
|
|
1089
|
+
/** The client must first authenticate itself with the proxy. */
|
|
1090
|
+
HttpStatus[HttpStatus["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
1025
1091
|
/**
|
|
1026
1092
|
* The server timed out waiting for the request. According to HTTP specifications: "The client did
|
|
1027
1093
|
* not produce a request within the time that the server was prepared to wait. The client MAY
|
|
1028
1094
|
* repeat the request without modifications at any later time."
|
|
1029
|
-
*/
|
|
1095
|
+
*/
|
|
1096
|
+
HttpStatus[HttpStatus["RequestTimeout"] = 408] = "RequestTimeout";
|
|
1030
1097
|
/**
|
|
1031
1098
|
* Indicates that the request could not be processed because of conflict in the request, such as
|
|
1032
1099
|
* an edit conflict between multiple simultaneous updates.
|
|
1033
|
-
*/
|
|
1100
|
+
*/
|
|
1101
|
+
HttpStatus[HttpStatus["Conflict"] = 409] = "Conflict";
|
|
1034
1102
|
/**
|
|
1035
1103
|
* Indicates that the resource requested is no longer available and will not be available again.
|
|
1036
1104
|
* This should be used when a resource has been intentionally removed and the resource should be
|
|
@@ -1038,101 +1106,143 @@ async function runValidators(requestEv, validators, data, devMode) {
|
|
|
1038
1106
|
* future. Clients such as search engines should remove the resource from their indices. Most use
|
|
1039
1107
|
* cases do not require clients and search engines to purge the resource, and a "404 Not Found"
|
|
1040
1108
|
* may be used instead.
|
|
1041
|
-
*/
|
|
1109
|
+
*/
|
|
1110
|
+
HttpStatus[HttpStatus["Gone"] = 410] = "Gone";
|
|
1042
1111
|
/**
|
|
1043
1112
|
* The request did not specify the length of its content, which is required by the requested
|
|
1044
1113
|
* resource.
|
|
1045
|
-
*/
|
|
1046
|
-
|
|
1114
|
+
*/
|
|
1115
|
+
HttpStatus[HttpStatus["LengthRequired"] = 411] = "LengthRequired";
|
|
1116
|
+
/** The server does not meet one of the preconditions that the requester put on the request. */
|
|
1117
|
+
HttpStatus[HttpStatus["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
1047
1118
|
/**
|
|
1048
1119
|
* The request is larger than the server is willing or able to process. Previously called "Request
|
|
1049
1120
|
* Entity Too Large".
|
|
1050
|
-
*/
|
|
1121
|
+
*/
|
|
1122
|
+
HttpStatus[HttpStatus["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
1051
1123
|
/**
|
|
1052
1124
|
* The URI provided was too long for the server to process. Often the result of too much data
|
|
1053
1125
|
* being encoded as a query-string of a GET request, in which case it should be converted to a
|
|
1054
1126
|
* POST request. Called "Request-URI Too Long" previously.
|
|
1055
|
-
*/
|
|
1127
|
+
*/
|
|
1128
|
+
HttpStatus[HttpStatus["UriTooLong"] = 414] = "UriTooLong";
|
|
1056
1129
|
/**
|
|
1057
1130
|
* The request entity has a media type which the server or resource does not support. For example,
|
|
1058
1131
|
* the client uploads an image as image/svg+xml, but the server requires that images use a
|
|
1059
1132
|
* different format.
|
|
1060
|
-
*/
|
|
1133
|
+
*/
|
|
1134
|
+
HttpStatus[HttpStatus["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
1061
1135
|
/**
|
|
1062
1136
|
* The client has asked for a portion of the file (byte serving), but the server cannot supply
|
|
1063
1137
|
* that portion. For example, if the client asked for a part of the file that lies beyond the end
|
|
1064
1138
|
* of the file. Called "Requested Range Not Satisfiable" previously.
|
|
1065
|
-
*/
|
|
1066
|
-
|
|
1139
|
+
*/
|
|
1140
|
+
HttpStatus[HttpStatus["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
1141
|
+
/** The server cannot meet the requirements of the Expect request-header field. */
|
|
1142
|
+
HttpStatus[HttpStatus["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
1067
1143
|
/**
|
|
1068
1144
|
* This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324,
|
|
1069
1145
|
* Hyper Text Coffee Pot Control Protocol, and is not expected to be implemented by actual HTTP
|
|
1070
1146
|
* servers. The RFC specifies this code should be returned by teapots requested to brew coffee.
|
|
1071
1147
|
* This HTTP status is used as an Easter egg in some websites, including Google.com.
|
|
1072
|
-
*/
|
|
1148
|
+
*/
|
|
1149
|
+
HttpStatus[HttpStatus["IAmATeapot"] = 418] = "IAmATeapot";
|
|
1073
1150
|
/**
|
|
1074
1151
|
* The request was directed at a server that is not able to produce a response (for example
|
|
1075
1152
|
* because a connection reuse).
|
|
1076
|
-
*/
|
|
1077
|
-
|
|
1078
|
-
/** The
|
|
1079
|
-
|
|
1153
|
+
*/
|
|
1154
|
+
HttpStatus[HttpStatus["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
1155
|
+
/** The request was well-formed but was unable to be followed due to semantic errors. */
|
|
1156
|
+
HttpStatus[HttpStatus["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
1157
|
+
/** The resource that is being accessed is locked. */
|
|
1158
|
+
HttpStatus[HttpStatus["Locked"] = 423] = "Locked";
|
|
1159
|
+
/** The request failed due to failure of a previous request (e.g., a PROPPATCH). */
|
|
1160
|
+
HttpStatus[HttpStatus["FailedDependency"] = 424] = "FailedDependency";
|
|
1080
1161
|
/**
|
|
1081
1162
|
* The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header
|
|
1082
1163
|
* field.
|
|
1083
|
-
*/
|
|
1164
|
+
*/
|
|
1165
|
+
HttpStatus[HttpStatus["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
1084
1166
|
/**
|
|
1085
1167
|
* The origin server requires the request to be conditional. Intended to prevent "the 'lost
|
|
1086
1168
|
* update' problem, where a client GETs a resource's state, modifies it, and PUTs it back to the
|
|
1087
1169
|
* server, when meanwhile a third party has modified the state on the server, leading to a
|
|
1088
1170
|
* conflict."
|
|
1089
|
-
*/
|
|
1171
|
+
*/
|
|
1172
|
+
HttpStatus[HttpStatus["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
1090
1173
|
/**
|
|
1091
1174
|
* The user has sent too many requests in a given amount of time. Intended for use with
|
|
1092
1175
|
* rate-limiting schemes.
|
|
1093
|
-
*/
|
|
1176
|
+
*/
|
|
1177
|
+
HttpStatus[HttpStatus["TooManyRequests"] = 429] = "TooManyRequests";
|
|
1094
1178
|
/**
|
|
1095
1179
|
* The server is unwilling to process the request because either an individual header field, or
|
|
1096
1180
|
* all the header fields collectively, are too large.
|
|
1097
|
-
*/
|
|
1181
|
+
*/
|
|
1182
|
+
HttpStatus[HttpStatus["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
1098
1183
|
/**
|
|
1099
1184
|
* A server operator has received a legal demand to deny access to a resource or to a set of
|
|
1100
1185
|
* resources that includes the requested resource. The code 451 was chosen as a reference to the
|
|
1101
1186
|
* novel Fahrenheit 451.
|
|
1102
|
-
*/
|
|
1187
|
+
*/
|
|
1188
|
+
HttpStatus[HttpStatus["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
1103
1189
|
/**
|
|
1104
1190
|
* A generic error message, given when an unexpected condition was encountered and no more
|
|
1105
1191
|
* specific message is suitable.
|
|
1106
|
-
*/
|
|
1192
|
+
*/
|
|
1193
|
+
HttpStatus[HttpStatus["InternalServerError"] = 500] = "InternalServerError";
|
|
1107
1194
|
/**
|
|
1108
1195
|
* The server either does not recognize the request method, or it lacks the ability to fulfill the
|
|
1109
1196
|
* request. Usually this implies future availability (e.g., a new feature of a web-service API).
|
|
1110
|
-
*/
|
|
1197
|
+
*/
|
|
1198
|
+
HttpStatus[HttpStatus["NotImplemented"] = 501] = "NotImplemented";
|
|
1111
1199
|
/**
|
|
1112
1200
|
* The server was acting as a gateway or proxy and received an invalid response from the upstream
|
|
1113
1201
|
* server.
|
|
1114
|
-
*/
|
|
1202
|
+
*/
|
|
1203
|
+
HttpStatus[HttpStatus["BadGateway"] = 502] = "BadGateway";
|
|
1115
1204
|
/**
|
|
1116
1205
|
* The server is currently unavailable (because it is overloaded or down for maintenance).
|
|
1117
1206
|
* Generally, this is a temporary state.
|
|
1118
|
-
*/
|
|
1207
|
+
*/
|
|
1208
|
+
HttpStatus[HttpStatus["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
1119
1209
|
/**
|
|
1120
1210
|
* The server was acting as a gateway or proxy and did not receive a timely response from the
|
|
1121
1211
|
* upstream server.
|
|
1122
|
-
*/
|
|
1123
|
-
|
|
1124
|
-
/**
|
|
1125
|
-
|
|
1126
|
-
/**
|
|
1127
|
-
|
|
1212
|
+
*/
|
|
1213
|
+
HttpStatus[HttpStatus["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
1214
|
+
/** The server does not support the HTTP protocol version used in the request */
|
|
1215
|
+
HttpStatus[HttpStatus["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
|
|
1216
|
+
/** Transparent content negotiation for the request results in a circular reference. */
|
|
1217
|
+
HttpStatus[HttpStatus["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
1218
|
+
/** The server is unable to store the representation needed to complete the request. */
|
|
1219
|
+
HttpStatus[HttpStatus["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
1220
|
+
/** The server detected an infinite loop while processing the request. */
|
|
1221
|
+
HttpStatus[HttpStatus["LoopDetected"] = 508] = "LoopDetected";
|
|
1222
|
+
/** Further extensions to the request are required for the server to fulfill it. */
|
|
1223
|
+
HttpStatus[HttpStatus["NotExtended"] = 510] = "NotExtended";
|
|
1128
1224
|
/**
|
|
1129
1225
|
* The client needs to authenticate to gain network access. Intended for use by intercepting
|
|
1130
1226
|
* proxies used to control access to the network (e.g., "captive portals" used to require
|
|
1131
1227
|
* agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
|
|
1132
|
-
*/
|
|
1228
|
+
*/
|
|
1229
|
+
HttpStatus[HttpStatus["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
1133
1230
|
return HttpStatus;
|
|
1134
1231
|
}({});
|
|
1135
|
-
|
|
1232
|
+
/** Client-controlled forwarded headers only override the URL when the proxy is trusted. */
|
|
1233
|
+
function getServerDataUrl(originalUrl, headers, trustForwardedHeaders) {
|
|
1234
|
+
const url = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
|
|
1235
|
+
if (!trustForwardedHeaders) return url.href;
|
|
1236
|
+
const host = headers.get("X-Forwarded-Host");
|
|
1237
|
+
const protocol = headers.get("X-Forwarded-Proto");
|
|
1238
|
+
if (host) {
|
|
1239
|
+
url.port = "";
|
|
1240
|
+
url.host = host;
|
|
1241
|
+
}
|
|
1242
|
+
if (protocol) url.protocol = protocol;
|
|
1243
|
+
return url.href;
|
|
1244
|
+
}
|
|
1245
|
+
function getQwikRouterServerData(requestEv, trustForwardedHeaders) {
|
|
1136
1246
|
const { params, request, status, locale, originalUrl } = requestEv;
|
|
1137
1247
|
const requestHeaders = {};
|
|
1138
1248
|
request.headers.forEach((value, key) => requestHeaders[key] = value);
|
|
@@ -1141,19 +1251,10 @@ function getQwikRouterServerData(requestEv) {
|
|
|
1141
1251
|
const formData = requestEv.sharedMap.get(RequestEvSharedActionFormData);
|
|
1142
1252
|
const routeName = requestEv.sharedMap.get(RequestRouteName);
|
|
1143
1253
|
const nonce = requestEv.sharedMap.get(RequestEvSharedNonce);
|
|
1144
|
-
const headers = requestEv.request.headers;
|
|
1145
|
-
const reconstructedUrl = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
|
|
1146
|
-
const host = headers.get("X-Forwarded-Host");
|
|
1147
|
-
const protocol = headers.get("X-Forwarded-Proto");
|
|
1148
|
-
if (host) {
|
|
1149
|
-
reconstructedUrl.port = "";
|
|
1150
|
-
reconstructedUrl.host = host;
|
|
1151
|
-
}
|
|
1152
|
-
if (protocol) reconstructedUrl.protocol = protocol;
|
|
1153
1254
|
const routeLoaderCtx = getRouteLoaderCtx(requestEv);
|
|
1154
1255
|
const loaderValues = getRouteLoaderValues(requestEv);
|
|
1155
1256
|
return {
|
|
1156
|
-
url:
|
|
1257
|
+
url: getServerDataUrl(originalUrl, request.headers, trustForwardedHeaders),
|
|
1157
1258
|
requestHeaders,
|
|
1158
1259
|
renderMode: getRequestMode(requestEv),
|
|
1159
1260
|
locale: locale(),
|
|
@@ -1187,7 +1288,8 @@ function createResolveRequestHandlers() {
|
|
|
1187
1288
|
/**
|
|
1188
1289
|
* JSON request wrapper must be before all middleware so it can rewrite the URL and catch
|
|
1189
1290
|
* redirects/errors from plugin/route middleware via try/catch on next()
|
|
1190
|
-
*/
|
|
1291
|
+
*/
|
|
1292
|
+
requestHandlers.push(jsonRequestWrapper());
|
|
1191
1293
|
requestHandlers.push(serverErrorMiddleware(route, renderHandler));
|
|
1192
1294
|
}
|
|
1193
1295
|
if (serverPlugins) _resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, serverPlugins, isPageRoute, method);
|
|
@@ -1314,16 +1416,17 @@ function createResolveRequestHandlers() {
|
|
|
1314
1416
|
}
|
|
1315
1417
|
function loadersMiddleware(routeLoaders, route) {
|
|
1316
1418
|
return (requestEvent) => {
|
|
1317
|
-
|
|
1318
|
-
|
|
1419
|
+
const requestEv = requestEvent;
|
|
1420
|
+
if (requestEv.headersSent) {
|
|
1421
|
+
requestEv.exit();
|
|
1319
1422
|
return;
|
|
1320
1423
|
}
|
|
1321
1424
|
if (routeLoaders.length === 0) return;
|
|
1322
|
-
setLoaderData(
|
|
1425
|
+
setLoaderData(requestEv, routeLoaders, route);
|
|
1323
1426
|
let allBlockSSRLoaders;
|
|
1324
1427
|
for (let i = 0; i < routeLoaders.length; i++) {
|
|
1325
1428
|
const loader = routeLoaders[i];
|
|
1326
|
-
const promise = loadRouteLoader(loader,
|
|
1429
|
+
const promise = loadRouteLoader(loader, requestEv);
|
|
1327
1430
|
promise.catch(() => {});
|
|
1328
1431
|
if (loader.__blockSSR) allBlockSSRLoaders = allBlockSSRLoaders ? allBlockSSRLoaders.then(() => promise) : promise;
|
|
1329
1432
|
}
|
|
@@ -1334,6 +1437,7 @@ function createResolveRequestHandlers() {
|
|
|
1334
1437
|
if (routeLoaders.length === 0) return;
|
|
1335
1438
|
const routeLoaderCtx = getRouteLoaderCtx(requestEv);
|
|
1336
1439
|
if (route.$loaderPaths$) Object.assign(routeLoaderCtx.loaderPaths, route.$loaderPaths$);
|
|
1440
|
+
if (route.$loaderParams$) Object.assign(getRouteLoaderParams(requestEv), route.$loaderParams$);
|
|
1337
1441
|
setRouteLoaders(requestEv, routeLoaders);
|
|
1338
1442
|
}
|
|
1339
1443
|
function eTagMiddleware(route) {
|
|
@@ -1344,17 +1448,18 @@ function createResolveRequestHandlers() {
|
|
|
1344
1448
|
if (!mods.some((m) => {
|
|
1345
1449
|
if (!m) return false;
|
|
1346
1450
|
if (m.routeConfig) return typeof m.routeConfig === "function" || m.routeConfig.eTag !== void 0 || m.routeConfig.cacheKey !== void 0;
|
|
1347
|
-
|
|
1451
|
+
const page = m;
|
|
1452
|
+
return page.eTag !== void 0 || page.cacheKey !== void 0;
|
|
1348
1453
|
})) return;
|
|
1349
1454
|
const loaderValues = getRouteLoaderValues(requestEv);
|
|
1350
|
-
const getData = (loaderOrAction) => {
|
|
1455
|
+
const getData = ((loaderOrAction) => {
|
|
1351
1456
|
const id = loaderOrAction.__id;
|
|
1352
1457
|
if (loaderOrAction.__brand === "server_loader") {
|
|
1353
1458
|
if (!(id in loaderValues)) throw new Error("Loader not executed for this request.");
|
|
1354
1459
|
return loaderValues[id];
|
|
1355
1460
|
}
|
|
1356
1461
|
return requestEv.sharedMap.get("@actionId") === id ? requestEv.sharedMap.get("@actionResult") : void 0;
|
|
1357
|
-
};
|
|
1462
|
+
});
|
|
1358
1463
|
const routeLocation = {
|
|
1359
1464
|
params: requestEv.params,
|
|
1360
1465
|
url: requestEv.url,
|
|
@@ -1490,7 +1595,8 @@ function createResolveRequestHandlers() {
|
|
|
1490
1595
|
* Prerendered pages are pruned from the production server route plan, so a request missing the
|
|
1491
1596
|
* canonical trailing slash lands here as not found. Redirect it when the canonical path was
|
|
1492
1597
|
* prerendered, and leave a genuine 404 alone.
|
|
1493
|
-
*/
|
|
1598
|
+
*/
|
|
1599
|
+
function fixStaticTrailingSlash(ev) {
|
|
1494
1600
|
const canonicalUrl = new URL(ev.originalUrl);
|
|
1495
1601
|
canonicalUrl.pathname = globalThis.__NO_TRAILING_SLASH__ ? canonicalUrl.pathname.replace(/\/$/, "") : ensureSlash(canonicalUrl.pathname);
|
|
1496
1602
|
if (isStaticPath(ev.request.method, canonicalUrl)) fixTrailingSlash(ev);
|
|
@@ -1534,7 +1640,7 @@ function createResolveRequestHandlers() {
|
|
|
1534
1640
|
The request origin "${inputOrigin}" does not match the server origin "${origin}".`);
|
|
1535
1641
|
}
|
|
1536
1642
|
}
|
|
1537
|
-
function renderQwikMiddleware(render) {
|
|
1643
|
+
function renderQwikMiddleware(render, trustForwardedHeaders = false) {
|
|
1538
1644
|
return async (requestEv) => {
|
|
1539
1645
|
if (requestEv.headersSent) return;
|
|
1540
1646
|
const responseHeaders = requestEv.headers;
|
|
@@ -1566,7 +1672,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1566
1672
|
const stream = writable.getWriter();
|
|
1567
1673
|
try {
|
|
1568
1674
|
const isStatic = getRequestMode(requestEv) === "static";
|
|
1569
|
-
const serverData = getQwikRouterServerData(requestEv);
|
|
1675
|
+
const serverData = getQwikRouterServerData(requestEv, trustForwardedHeaders);
|
|
1570
1676
|
const result = await render({
|
|
1571
1677
|
base: requestEv.basePathname + "build/",
|
|
1572
1678
|
stream,
|
|
@@ -1577,7 +1683,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1577
1683
|
...serverData.containerAttributes
|
|
1578
1684
|
},
|
|
1579
1685
|
onBeforeFirstFlush: (info) => {
|
|
1580
|
-
if (info.
|
|
1686
|
+
if (info.hasCaughtError) {
|
|
1581
1687
|
boundaryErrored = true;
|
|
1582
1688
|
noStoreSent = true;
|
|
1583
1689
|
overrodeCacheControl = responseHeaders.has("Cache-Control");
|
|
@@ -1586,8 +1692,8 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1586
1692
|
}
|
|
1587
1693
|
});
|
|
1588
1694
|
if (typeof result.html === "string") await stream.write(result.html);
|
|
1589
|
-
boundaryErrored ||= result.
|
|
1590
|
-
if (boundaryErrored) requestEv.sharedMap.set(
|
|
1695
|
+
boundaryErrored ||= result.hasCaughtError === true;
|
|
1696
|
+
if (boundaryErrored) requestEv.sharedMap.set(RequestEvCaughtError, true);
|
|
1591
1697
|
} finally {
|
|
1592
1698
|
try {
|
|
1593
1699
|
await stream.ready;
|
|
@@ -1598,7 +1704,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1598
1704
|
}
|
|
1599
1705
|
}
|
|
1600
1706
|
if (pipeError) throw pipeError;
|
|
1601
|
-
if (boundaryErrored && (noStoreSent ? cachePlan || overrodeCacheControl : !!cachePlan)) console.warn(`
|
|
1707
|
+
if (boundaryErrored && (noStoreSent ? cachePlan || overrodeCacheControl : !!cachePlan)) console.warn(`A <Catch> caught during SSR of ${requestEv.url.pathname} — configured caching disabled: ` + (noStoreSent ? "the response was sent with Cache-Control: no-store." : "the SSR cache was skipped (response headers were already sent)."));
|
|
1602
1708
|
if (cachePlan && cacheChunks && cacheChunks.length > 0 && !boundaryErrored) {
|
|
1603
1709
|
const totalLength = cacheChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1604
1710
|
const combined = new Uint8Array(totalLength);
|
|
@@ -1649,19 +1755,15 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1649
1755
|
};
|
|
1650
1756
|
}
|
|
1651
1757
|
var { actionsMiddleware, checkBrand, checkCSRF, fixStaticTrailingSlash, fixTrailingSlash, getPathname, isLastModulePageRoute, isQrl, loadersMiddleware, measure, renderQwikMiddleware, resolveRequestHandlers, streamServerFunctionResult, verifySerializable } = createResolveRequestHandlers();
|
|
1652
|
-
/** @public */
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
});
|
|
1662
|
-
};
|
|
1663
|
-
var COLOR_400 = "#006ce9";
|
|
1664
|
-
var COLOR_500 = "#713fc2";
|
|
1758
|
+
/** @public */
|
|
1759
|
+
function getErrorHtml(status, e) {
|
|
1760
|
+
let message = "Server Error";
|
|
1761
|
+
if (e != null) {
|
|
1762
|
+
if (typeof e.message === "string") message = e.message;
|
|
1763
|
+
else message = String(e);
|
|
1764
|
+
}
|
|
1765
|
+
return `<html>` + minimalHtmlResponse(status, message) + `</html>`;
|
|
1766
|
+
}
|
|
1665
1767
|
function minimalHtmlResponse(status, message) {
|
|
1666
1768
|
if (typeof status !== "number") status = 500;
|
|
1667
1769
|
if (typeof message === "string") message = escapeHtml(message);
|
|
@@ -1684,15 +1786,39 @@ function minimalHtmlResponse(status, message) {
|
|
|
1684
1786
|
<body><p><strong>${status}</strong> <span>${message}</span></p></body>
|
|
1685
1787
|
`;
|
|
1686
1788
|
}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1789
|
+
var ESCAPE_HTML = /[&<>]/g;
|
|
1790
|
+
var escapeHtml = (s) => {
|
|
1791
|
+
return s.replace(ESCAPE_HTML, (c) => {
|
|
1792
|
+
switch (c) {
|
|
1793
|
+
case "&": return "&";
|
|
1794
|
+
case "<": return "<";
|
|
1795
|
+
case ">": return ">";
|
|
1796
|
+
default: return "";
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
};
|
|
1800
|
+
var COLOR_400 = "#006ce9";
|
|
1801
|
+
var COLOR_500 = "#713fc2";
|
|
1802
|
+
var ensureError = (e) => e instanceof Error || typeof e === "object" && e !== null ? e : new Error(String(e));
|
|
1803
|
+
function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, basePathname = "/", routerConfig) {
|
|
1804
|
+
let resolve;
|
|
1805
|
+
const responsePromise = new Promise((r) => resolve = r);
|
|
1806
|
+
try {
|
|
1807
|
+
const requestEv = createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolve, routerConfig);
|
|
1808
|
+
return {
|
|
1809
|
+
response: responsePromise,
|
|
1810
|
+
requestEv,
|
|
1811
|
+
completion: _asyncRequestStore ? _asyncRequestStore.run(requestEv, runNext, requestEv, rebuildRouteInfo, resolve) : runNext(requestEv, rebuildRouteInfo, resolve)
|
|
1812
|
+
};
|
|
1813
|
+
} catch (e) {
|
|
1814
|
+
resolve(null);
|
|
1815
|
+
return {
|
|
1816
|
+
response: responsePromise,
|
|
1817
|
+
requestEv: { headersSent: false },
|
|
1818
|
+
completion: Promise.resolve(ensureError(e))
|
|
1819
|
+
};
|
|
1692
1820
|
}
|
|
1693
|
-
return `<html>` + minimalHtmlResponse(status, message) + `</html>`;
|
|
1694
1821
|
}
|
|
1695
|
-
var ensureError = (e) => e instanceof Error || typeof e === "object" && e !== null ? e : new Error(String(e));
|
|
1696
1822
|
async function runNext(requestEv, rebuildRouteInfo, resolve) {
|
|
1697
1823
|
try {
|
|
1698
1824
|
const isValidURL = (url) => new URL(url.pathname + url.search, url);
|
|
@@ -1754,23 +1880,4 @@ async function runNext(requestEv, rebuildRouteInfo, resolve) {
|
|
|
1754
1880
|
if (!requestEv.isDirty()) resolve(null);
|
|
1755
1881
|
}
|
|
1756
1882
|
}
|
|
1757
|
-
|
|
1758
|
-
let resolve;
|
|
1759
|
-
const responsePromise = new Promise((r) => resolve = r);
|
|
1760
|
-
try {
|
|
1761
|
-
const requestEv = createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolve);
|
|
1762
|
-
return {
|
|
1763
|
-
response: responsePromise,
|
|
1764
|
-
requestEv,
|
|
1765
|
-
completion: _asyncRequestStore ? _asyncRequestStore.run(requestEv, runNext, requestEv, rebuildRouteInfo, resolve) : runNext(requestEv, rebuildRouteInfo, resolve)
|
|
1766
|
-
};
|
|
1767
|
-
} catch (e) {
|
|
1768
|
-
resolve(null);
|
|
1769
|
-
return {
|
|
1770
|
-
response: responsePromise,
|
|
1771
|
-
requestEv: { headersSent: false },
|
|
1772
|
-
completion: Promise.resolve(ensureError(e))
|
|
1773
|
-
};
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
export { getStaticPathRedirect as a, clearSsrCache as c, mergeHeadersCookies as d, resolveRequestHandlers as i, RequestEvErrorBoundaryCaught as l, getErrorHtml as n, isStaticPath as o, renderQwikMiddleware as r, clearLoaderCache as s, runQwikRouter as t, RewriteMessage as u };
|
|
1883
|
+
export { getStaticPathRedirect as a, clearSsrCache as c, mergeHeadersCookies as d, resolveRequestHandlers as i, RequestEvCaughtError as l, getErrorHtml as n, isStaticPath as o, renderQwikMiddleware as r, clearLoaderCache as s, runQwikRouter as t, RewriteMessage as u };
|