@qwik.dev/router 2.0.0-beta.35 → 2.0.0-beta.37

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.
@@ -1,73 +1,13 @@
1
- import { Q as Q_ROUTE, m as resolveRouteConfig, n as QLOADER_KEY, h as QFN_KEY, j as QACTION_KEY, o as isPromise, k as QDATA_KEY, b as loadRoute } from '../../chunks/routing.qwik.mjs';
2
- import { isDev, _UNINITIALIZED, _deserialize, _verifySerializable, _serialize, _getAsyncLocalStorage } from '@qwik.dev/core/internal';
3
- import { inlinedQrl } from '@qwik.dev/core';
4
- import { R as RedirectMessage, A as AbortMessage } from '../../chunks/redirect-handler.mjs';
5
- import { isServer } from '@qwik.dev/core/build';
1
+ import { n as getRouteLoaderCtx, o as getRouteLoaderValues, i as Q_ROUTE, p as loadRouteLoader, q as setRouteLoaders, S as ServerError, t as RedirectMessage, k as QFN_KEY, Q as QACTION_KEY, A as AbortMessage, l as QDATA_KEY, _ as _asyncRequestStore, F as FULLPATH_HEADER } from '../../chunks/deepFreeze.qwik.mjs';
2
+ import { d as resolveRouteConfig, e as isPromise, l as loadRoute } from '../../chunks/head.qwik.mjs';
3
+ import { I as IsQLoader, Q as QLoaderId, a as QActionId, b as IsQAction, t as trimRecognizedInternalPathname, r as recognizeRequest, c as resolveValidInternalFullPathname, d as trimInternalPathname, L as LOADER_REGEX } from '../../chunks/request-path.mjs';
4
+ import { g as getRequestRoute, a as getRequestMode, R as RequestRouteName, b as RequestEvSharedNonce, c as RequestEvSharedActionId, d as RequestEvSharedActionFormData, e as RequestEvHttpStatusMessage, j as jsonRequestWrapper, l as loaderHandler, f as actionHandler, h as hash, n as normalizeETag, p as performETagMatch, s as setETagHeader, i as setCachedLoader, k as setCachedSsr, r as resolveETag, m as resolveCacheKey, M as MAX_CACHE_SIZE, o as getCachedLoader, q as getCachedSsr, t as defaultLoaderCacheKey, u as defaultSsrCacheKey, v as RequestEvShareServerTiming, w as RequestEvETagCacheKey, x as createRequestEventWithDeps } from '../../chunks/action-handler.mjs';
5
+ export { y as clearLoaderCache, z as clearSsrCache } from '../../chunks/action-handler.mjs';
6
+ import { isDev, inlinedQrl } from '@qwik.dev/core';
7
+ import { _verifySerializable, _serialize, isDev as isDev$1 } from '@qwik.dev/core/internal';
8
+ import { e as ensureSlash } from '../../chunks/pathname.mjs';
6
9
  import { g as getErrorHtml, m as minimalHtmlResponse } from '../../chunks/error-handler.mjs';
7
10
 
8
- const IsQData = "@isQData";
9
- const QDATA_JSON = "/q-data.json";
10
- function getRouteMatchPathname(pathname) {
11
- const isInternal = pathname.endsWith(QDATA_JSON);
12
- if (isInternal) {
13
- const trimEnd = pathname.length - QDATA_JSON.length + (globalThis.__NO_TRAILING_SLASH__ ? 0 : 1);
14
- pathname = pathname.slice(0, trimEnd);
15
- if (pathname === "") {
16
- pathname = "/";
17
- }
18
- }
19
- return {
20
- pathname,
21
- isInternal
22
- };
23
- }
24
-
25
- const MAX_CACHE_SIZE = typeof globalThis.__SSR_CACHE_SIZE__ === "number" ? globalThis.__SSR_CACHE_SIZE__ : 50;
26
- const ssrCache = /* @__PURE__ */ new Map();
27
- function resolveETag(eTagExport, headProps) {
28
- if (eTagExport === void 0) {
29
- return null;
30
- }
31
- if (typeof eTagExport === "function") {
32
- return eTagExport(headProps);
33
- }
34
- return eTagExport;
35
- }
36
- function resolveCacheKey(cacheKeyExport, status, eTag, pathname) {
37
- if (cacheKeyExport === true) {
38
- return `${status}|${eTag}|${pathname}`;
39
- }
40
- if (typeof cacheKeyExport !== "function") {
41
- return null;
42
- }
43
- return cacheKeyExport(status, eTag, pathname);
44
- }
45
- function getCachedHtml(key) {
46
- const html = ssrCache.get(key);
47
- if (html !== void 0) {
48
- ssrCache.delete(key);
49
- ssrCache.set(key, html);
50
- }
51
- return html;
52
- }
53
- function setCachedHtml(key, html) {
54
- if (MAX_CACHE_SIZE <= 0) {
55
- return;
56
- }
57
- if (ssrCache.size >= MAX_CACHE_SIZE) {
58
- const firstKey = ssrCache.keys().next().value;
59
- ssrCache.delete(firstKey);
60
- }
61
- ssrCache.set(key, html);
62
- }
63
- function clearSsrCache(cacheKey) {
64
- if (cacheKey != null) {
65
- ssrCache.delete(cacheKey);
66
- } else {
67
- ssrCache.clear();
68
- }
69
- }
70
-
71
11
  var HttpStatus = /* @__PURE__ */ (function(HttpStatus2) {
72
12
  HttpStatus2[HttpStatus2["Continue"] = 100] = "Continue";
73
13
  HttpStatus2[HttpStatus2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
@@ -133,457 +73,12 @@ var HttpStatus = /* @__PURE__ */ (function(HttpStatus2) {
133
73
  return HttpStatus2;
134
74
  })({});
135
75
 
136
- const RequestEvLoaders = /* @__PURE__ */ Symbol("RequestEvLoaders");
137
- const RequestEvMode = /* @__PURE__ */ Symbol("RequestEvMode");
138
- const RequestEvRoute = /* @__PURE__ */ Symbol("RequestEvRoute");
139
- const RequestEvLoaderSerializationStrategyMap = /* @__PURE__ */ Symbol("RequestEvLoaderSerializationStrategyMap");
140
- const RequestRouteName = "@routeName";
141
- const RequestEvSharedActionId = "@actionId";
142
- const RequestEvSharedActionFormData = "@actionFormData";
143
- const RequestEvSharedNonce = "@nonce";
144
- const RequestEvIsRewrite = "@rewrite";
145
- const RequestEvShareServerTiming = "@serverTiming";
146
- const RequestEvETagCacheKey = "@eTagCacheKey";
147
- const RequestEvHttpStatusMessage = "@httpStatusMessage";
148
- const RequestEvShareQData = "qData";
149
- function getRequestLoaders(requestEv) {
150
- return requestEv[RequestEvLoaders];
151
- }
152
- function getRequestLoaderSerializationStrategyMap(requestEv) {
153
- return requestEv[RequestEvLoaderSerializationStrategyMap];
154
- }
155
- function getRequestRoute(requestEv) {
156
- return requestEv[RequestEvRoute];
157
- }
158
- function getRequestMode(requestEv) {
159
- return requestEv[RequestEvMode];
160
- }
161
- const ABORT_INDEX = Number.MAX_SAFE_INTEGER;
162
- const isDangerousKey = (k) => k === "__proto__" || k === "constructor" || k === "prototype";
163
- const isArrayIndexKey = (k) => /^(0|[1-9]\d*)$/.test(k);
164
- const getArrayPaths = (formData) => {
165
- const arrayCandidates = /* @__PURE__ */ new Map();
166
- for (const [name] of formData) {
167
- const keys = name.split(".");
168
- let hasDangerousKey = false;
169
- for (const key of keys) {
170
- if (isDangerousKey(key)) {
171
- hasDangerousKey = true;
172
- break;
173
- }
174
- }
175
- if (hasDangerousKey) {
176
- continue;
177
- }
178
- let path = "";
179
- for (let i = 0; i < keys.length - 1; i++) {
180
- const key = keys[i];
181
- if (key.endsWith("[]")) {
182
- break;
183
- }
184
- path = path ? `${path}.${key}` : key;
185
- if (!arrayCandidates.has(path)) {
186
- arrayCandidates.set(path, true);
187
- }
188
- if (!isArrayIndexKey(keys[i + 1])) {
189
- arrayCandidates.set(path, false);
190
- }
191
- }
192
- }
193
- return new Set(Array.from(arrayCandidates.entries()).filter(([, isArrayPath]) => isArrayPath).map(([path]) => path));
194
- };
195
- const formToObj = (formData) => {
196
- const values = /* @__PURE__ */ Object.create(null);
197
- const arrayPaths = getArrayPaths(formData);
198
- for (const [name, value] of formData) {
199
- const keys = name.split(".");
200
- let hasDangerousKey = false;
201
- for (let i = 0; i < keys.length; i++) {
202
- if (isDangerousKey(keys[i])) {
203
- hasDangerousKey = true;
204
- break;
205
- }
206
- }
207
- if (hasDangerousKey) {
208
- continue;
209
- }
210
- let object = values;
211
- let path = "";
212
- for (let i = 0; i < keys.length; i++) {
213
- const key = keys[i];
214
- if (key.endsWith("[]")) {
215
- const arrayKey = key.slice(0, -2);
216
- if (isDangerousKey(arrayKey)) {
217
- break;
218
- }
219
- const existingValue = object[arrayKey];
220
- if (existingValue !== void 0 && !Array.isArray(existingValue)) {
221
- break;
222
- }
223
- object[arrayKey] = existingValue || [];
224
- object[arrayKey].push(value);
225
- break;
226
- }
227
- if (Array.isArray(object) && !isArrayIndexKey(key)) {
228
- break;
229
- }
230
- if (i < keys.length - 1) {
231
- path = path ? `${path}.${key}` : key;
232
- const nextValue = object[key];
233
- if (nextValue !== void 0) {
234
- object = nextValue;
235
- continue;
236
- }
237
- object = object[key] = arrayPaths.has(path) ? [] : /* @__PURE__ */ Object.create(null);
238
- } else {
239
- object[key] = value;
240
- }
241
- }
242
- }
243
- return values;
244
- };
245
- const parseRequest = async (deps, { request, method, query }, sharedMap) => {
246
- const type = deps.getContentType(request.headers);
247
- if (type === "application/x-www-form-urlencoded" || type === "multipart/form-data") {
248
- const formData = await request.formData();
249
- sharedMap.set(RequestEvSharedActionFormData, formData);
250
- return formToObj(formData);
251
- } else if (type === "application/json") {
252
- const data = await request.json();
253
- return data;
254
- } else if (type === "application/qwik-json") {
255
- if (method === "GET" && query.has(deps.QDATA_KEY)) {
256
- const data = query.get(deps.QDATA_KEY);
257
- if (data) {
258
- try {
259
- return _deserialize(decodeURIComponent(data));
260
- } catch {
261
- }
262
- }
263
- }
264
- return _deserialize(await request.text());
265
- }
266
- return void 0;
267
- };
268
- function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestHandlers, basePathname, resolved) {
269
- const { request, platform, env } = serverRequestEv;
270
- const sharedMap = /* @__PURE__ */ new Map();
271
- const cookie = new deps.Cookie(request.headers.get("cookie"));
272
- const headers = new Headers();
273
- const url = new URL(request.url);
274
- const { pathname, isInternal } = deps.getRouteMatchPathname(url.pathname);
275
- if (isInternal) {
276
- url.pathname = pathname;
277
- sharedMap.set(deps.IsQData, true);
278
- }
279
- let routeModuleIndex = -1;
280
- let writableStream = null;
281
- let requestData = void 0;
282
- let locale = serverRequestEv.locale;
283
- let status = loadedRoute?.$notFound$ ? 404 : 200;
284
- const next = async () => {
285
- routeModuleIndex++;
286
- while (routeModuleIndex < requestHandlers.length) {
287
- const moduleRequestHandler = requestHandlers[routeModuleIndex];
288
- const result = moduleRequestHandler(requestEv);
289
- if (deps.isPromise(result)) {
290
- await result;
291
- }
292
- routeModuleIndex++;
293
- }
294
- };
295
- const resetRoute = (_loadedRoute, _requestHandlers, _url = url) => {
296
- loadedRoute = _loadedRoute;
297
- status = loadedRoute?.$notFound$ ? 404 : 200;
298
- requestHandlers = _requestHandlers;
299
- url.pathname = _url.pathname;
300
- url.search = _url.search;
301
- routeModuleIndex = -1;
302
- };
303
- const check = () => {
304
- if (writableStream !== null) {
305
- throw new Error("Response already sent");
306
- }
307
- };
308
- const send = (statusOrResponse, body) => {
309
- check();
310
- if (typeof statusOrResponse === "number") {
311
- status = statusOrResponse;
312
- const writableStream2 = requestEv.getWritableStream();
313
- const writer = writableStream2.getWriter();
314
- writer.write(typeof body === "string" ? deps.encoder.encode(body) : body);
315
- writer.close();
316
- } else {
317
- status = statusOrResponse.status;
318
- statusOrResponse.headers.forEach((value, key) => {
319
- if (key.toLowerCase() === "set-cookie") {
320
- return;
321
- }
322
- headers.append(key, value);
323
- });
324
- statusOrResponse.headers.getSetCookie().forEach((ck) => {
325
- const index = ck.indexOf("=");
326
- if (index === -1) {
327
- return;
328
- }
329
- const key = ck.slice(0, index).trim();
330
- const value = ck.slice(index + 1).trim();
331
- cookie.set(key, value);
332
- });
333
- if (statusOrResponse.body) {
334
- const writableStream2 = requestEv.getWritableStream();
335
- statusOrResponse.body.pipeTo(writableStream2);
336
- } else {
337
- requestEv.getWritableStream().getWriter().close();
338
- }
339
- }
340
- return exit();
341
- };
342
- const exit = (message = new deps.AbortMessage()) => {
343
- routeModuleIndex = ABORT_INDEX;
344
- return message;
345
- };
346
- const loaders = {};
347
- const requestEv = {
348
- [RequestEvLoaders]: loaders,
349
- [RequestEvLoaderSerializationStrategyMap]: /* @__PURE__ */ new Map(),
350
- [RequestEvMode]: serverRequestEv.mode,
351
- get [RequestEvRoute]() {
352
- return loadedRoute;
353
- },
354
- cookie,
355
- headers,
356
- env,
357
- method: request.method,
358
- signal: request.signal,
359
- originalUrl: new URL(url),
360
- get params() {
361
- return loadedRoute?.$params$ ?? {};
362
- },
363
- get pathname() {
364
- return url.pathname;
365
- },
366
- platform,
367
- get query() {
368
- return url.searchParams;
369
- },
370
- request,
371
- url,
372
- basePathname,
373
- sharedMap,
374
- get headersSent() {
375
- return writableStream !== null;
376
- },
377
- get exited() {
378
- return routeModuleIndex >= ABORT_INDEX;
379
- },
380
- get clientConn() {
381
- return serverRequestEv.getClientConn();
382
- },
383
- next,
384
- resetRoute,
385
- exit,
386
- cacheControl: (cacheControl, target = "Cache-Control") => {
387
- check();
388
- headers.set(target, deps.createCacheControl(cacheControl));
389
- },
390
- resolveValue: async (loaderOrAction) => {
391
- const id = loaderOrAction.__id;
392
- if (loaderOrAction.__brand === "server_loader") {
393
- if (!(id in loaders)) {
394
- throw new Error("You can not get the returned data of a loader that has not been executed for this request.");
395
- }
396
- if (loaders[id] === _UNINITIALIZED) {
397
- await deps.getRouteLoaderPromise(loaderOrAction, loaders, requestEv[RequestEvLoaderSerializationStrategyMap], requestEv);
398
- }
399
- }
400
- return loaders[id];
401
- },
402
- status: (statusCode) => {
403
- if (typeof statusCode === "number") {
404
- check();
405
- status = statusCode;
406
- return statusCode;
407
- }
408
- return status;
409
- },
410
- locale: (_locale) => {
411
- if (typeof _locale === "string") {
412
- locale = _locale;
413
- }
414
- return locale || "";
415
- },
416
- error: (statusCode, message) => {
417
- status = statusCode;
418
- headers.delete("Cache-Control");
419
- return new deps.ServerError(statusCode, message);
420
- },
421
- redirect: (statusCode, url2) => {
422
- check();
423
- status = statusCode;
424
- if (url2) {
425
- if (
426
- // //test.com
427
- /^\/\//.test(url2) || // /test//path
428
- /([^:])\/\/+/.test(url2)
429
- ) {
430
- const fixedURL = url2.replace(/^\/\/+/, "/").replace(/([^:])\/\/+/g, "$1/");
431
- console.warn(`Redirect URL ${url2} is invalid, fixing to ${fixedURL}`);
432
- url2 = fixedURL;
433
- }
434
- headers.set("Location", url2);
435
- }
436
- headers.delete("Cache-Control");
437
- if (statusCode > 301) {
438
- headers.set("Cache-Control", "no-store");
439
- }
440
- return exit(new deps.RedirectMessage());
441
- },
442
- rewrite: (pathname2) => {
443
- check();
444
- if (pathname2.startsWith("http")) {
445
- throw new deps.ServerError(400, isDev ? "Rewrite does not support absolute urls" : "Bad Request");
446
- }
447
- sharedMap.set(RequestEvIsRewrite, true);
448
- return exit(new deps.RewriteMessage(pathname2.replace(/\/+/g, "/")));
449
- },
450
- defer: (returnData) => {
451
- return typeof returnData === "function" ? returnData : () => returnData;
452
- },
453
- fail: (statusCode, data) => {
454
- check();
455
- status = statusCode;
456
- headers.delete("Cache-Control");
457
- return {
458
- failed: true,
459
- ...data
460
- };
461
- },
462
- text: (statusCode, text) => {
463
- headers.set("Content-Type", "text/plain; charset=utf-8");
464
- return send(statusCode, text);
465
- },
466
- html: (statusCode, html) => {
467
- headers.set("Content-Type", "text/html; charset=utf-8");
468
- return send(statusCode, html);
469
- },
470
- parseBody: async () => {
471
- if (requestData !== void 0) {
472
- return requestData;
473
- }
474
- return requestData = parseRequest(deps, requestEv, sharedMap);
475
- },
476
- json: (statusCode, data) => {
477
- headers.set("Content-Type", "application/json; charset=utf-8");
478
- return send(statusCode, JSON.stringify(data));
479
- },
480
- send,
481
- isDirty: () => {
482
- return writableStream !== null;
483
- },
484
- getWritableStream: () => {
485
- if (writableStream === null) {
486
- if (isDev) {
487
- const serverTiming = sharedMap.get(RequestEvShareServerTiming);
488
- if (serverTiming) {
489
- headers.set("Server-Timing", serverTiming.map(([name, duration]) => `${name};dur=${duration}`).join(","));
490
- }
491
- }
492
- writableStream = serverRequestEv.getWritableStream(status, headers, cookie, resolved, requestEv);
493
- }
494
- return writableStream;
495
- }
496
- };
497
- return requestEv;
498
- }
499
-
500
- function verifySerializable(data, qrl) {
501
- try {
502
- _verifySerializable(data, void 0);
503
- } catch (e) {
504
- if (e instanceof Error && qrl.dev) {
505
- e.loc = qrl.dev;
506
- }
507
- throw e;
508
- }
509
- }
510
- function now() {
511
- return typeof performance !== "undefined" ? performance.now() : 0;
512
- }
513
- async function measure(requestEv, name, fn) {
514
- const start = now();
515
- try {
516
- return await fn();
517
- } finally {
518
- const duration = now() - start;
519
- let measurements = requestEv.sharedMap.get("@serverTiming");
520
- if (!measurements) {
521
- requestEv.sharedMap.set("@serverTiming", measurements = []);
522
- }
523
- measurements.push([
524
- name,
525
- duration
526
- ]);
527
- }
528
- }
529
- async function runValidators(requestEv, validators, data) {
530
- let lastResult = {
531
- success: true,
532
- data
533
- };
534
- if (validators) {
535
- for (const validator of validators) {
536
- if (isDev) {
537
- lastResult = await measure(requestEv, `validator$`, () => validator.validate(requestEv, data));
538
- } else {
539
- lastResult = await validator.validate(requestEv, data);
540
- }
541
- if (!lastResult.success) {
542
- return lastResult;
543
- } else {
544
- data = lastResult.data;
545
- }
546
- }
547
- }
548
- return lastResult;
549
- }
550
- async function getRouteLoaderPromise(loader, loaders, loadersSerializationStrategy, requestEv) {
551
- const loaderId = loader.__id;
552
- loaders[loaderId] = runValidators(
553
- requestEv,
554
- loader.__validators,
555
- void 0
556
- // data
557
- ).then((res) => {
558
- if (res.success) {
559
- if (isDev) {
560
- return measure(requestEv, loader.__qrl.getHash(), () => loader.__qrl.call(requestEv, requestEv));
561
- } else {
562
- return loader.__qrl.call(requestEv, requestEv);
563
- }
564
- } else {
565
- return requestEv.fail(res.status ?? 500, res.error);
566
- }
567
- }).then((resolvedLoader) => {
568
- if (typeof resolvedLoader === "function") {
569
- loaders[loaderId] = resolvedLoader();
570
- } else {
571
- if (isDev) {
572
- verifySerializable(resolvedLoader, loader.__qrl);
573
- }
574
- loaders[loaderId] = resolvedLoader;
575
- }
576
- return resolvedLoader;
577
- });
578
- loadersSerializationStrategy.set(loaderId, loader.__serializationStrategy);
579
- return loaders[loaderId];
580
- }
581
-
582
76
  function getQwikRouterServerDataWithDeps(deps, requestEv) {
583
77
  const { params, request, status, locale, originalUrl } = requestEv;
584
78
  const requestHeaders = {};
585
79
  request.headers.forEach((value, key) => requestHeaders[key] = value);
586
80
  const action = requestEv.sharedMap.get(deps.RequestEvSharedActionId);
81
+ const actionResult = requestEv.sharedMap.get("@actionResult");
587
82
  const formData = requestEv.sharedMap.get(deps.RequestEvSharedActionFormData);
588
83
  const routeName = requestEv.sharedMap.get(deps.RequestRouteName);
589
84
  const nonce = requestEv.sharedMap.get(deps.RequestEvSharedNonce);
@@ -598,11 +93,12 @@ function getQwikRouterServerDataWithDeps(deps, requestEv) {
598
93
  if (protocol) {
599
94
  reconstructedUrl.protocol = protocol;
600
95
  }
601
- const loaders = deps.getRequestLoaders(requestEv);
602
- const loadersSerializationStrategy = deps.getRequestLoaderSerializationStrategyMap(requestEv);
96
+ const routeLoaderCtx = getRouteLoaderCtx(requestEv);
97
+ const loaderValues = getRouteLoaderValues(requestEv);
603
98
  return {
604
99
  url: reconstructedUrl.href,
605
100
  requestHeaders,
101
+ renderMode: deps.getRequestMode(requestEv),
606
102
  locale: locale(),
607
103
  nonce,
608
104
  containerAttributes: {
@@ -615,12 +111,13 @@ function getQwikRouterServerDataWithDeps(deps, requestEv) {
615
111
  ...params
616
112
  },
617
113
  loadedRoute: deps.getRequestRoute(requestEv),
114
+ routeLoaderCtx,
115
+ loaderValues,
618
116
  response: {
619
117
  status: status(),
620
118
  statusMessage: requestEv.sharedMap.get(deps.RequestEvHttpStatusMessage),
621
- loaders,
622
- loadersSerializationStrategy,
623
119
  action,
120
+ actionResult,
624
121
  formData
625
122
  }
626
123
  }
@@ -634,8 +131,7 @@ const responsePageDeps = {
634
131
  RequestEvSharedActionId,
635
132
  RequestEvSharedNonce,
636
133
  RequestRouteName,
637
- getRequestLoaders,
638
- getRequestLoaderSerializationStrategyMap,
134
+ getRequestMode,
639
135
  getRequestRoute
640
136
  };
641
137
  function getQwikRouterServerData(...args) {
@@ -643,22 +139,20 @@ function getQwikRouterServerData(...args) {
643
139
  }
644
140
 
645
141
  function createResolveRequestHandlers(deps) {
646
- const resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderHandler, isInternal) => {
142
+ const resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderHandler) => {
647
143
  const routeLoaders = [];
648
144
  const routeActions = [];
649
145
  const requestHandlers = [];
650
146
  const isPageRoute = !!isLastModulePageRoute(route.$mods$);
651
- if (isInternal) {
652
- requestHandlers.push(handleQDataRedirect);
653
- }
654
147
  if (isPageRoute) {
148
+ requestHandlers.push(jsonRequestWrapper());
655
149
  requestHandlers.push(serverErrorMiddleware(route, renderHandler));
656
150
  }
657
151
  if (serverPlugins) {
658
152
  _resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, serverPlugins, isPageRoute, method);
659
153
  }
660
154
  const routeModules = route.$mods$;
661
- _resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, isPageRoute, method);
155
+ _resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, isPageRoute, method, isPageRoute);
662
156
  const routeName = route.$routeName$;
663
157
  if (checkOrigin && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
664
158
  if (checkOrigin === "lax-proto") {
@@ -668,70 +162,32 @@ function createResolveRequestHandlers(deps) {
668
162
  }
669
163
  }
670
164
  if (isPageRoute) {
165
+ requestHandlers.push(loaderHandler(routeLoaders, route.$loaderPaths$));
166
+ requestHandlers.push(actionHandler(routeActions));
671
167
  if (method === "POST" || method === "GET") {
672
168
  requestHandlers.push(runServerFunction);
673
169
  }
674
170
  if (!route.$notFound$) {
675
171
  requestHandlers.push(fixTrailingSlash);
676
172
  }
677
- if (isInternal) {
678
- requestHandlers.push(renderQData);
679
- }
680
173
  }
681
174
  if (isPageRoute) {
682
175
  requestHandlers.push((ev) => {
683
176
  ev.sharedMap.set(deps.RequestRouteName, routeName);
684
177
  });
685
178
  requestHandlers.push(actionsMiddleware(routeActions));
686
- requestHandlers.push(loadersMiddleware(routeLoaders));
179
+ requestHandlers.push(loadersMiddleware(routeLoaders, route));
687
180
  requestHandlers.push(eTagMiddleware(route));
688
181
  requestHandlers.push(renderHandler);
689
182
  }
690
183
  return requestHandlers;
691
184
  };
692
- const _resolveRequestHandlers = (routeLoaders, routeActions, requestHandlers, routeModules, collectActions, method) => {
693
- for (const routeModule of routeModules) {
694
- if (typeof routeModule.onRequest === "function") {
695
- requestHandlers.push(routeModule.onRequest);
696
- } else if (Array.isArray(routeModule.onRequest)) {
697
- requestHandlers.push(...routeModule.onRequest);
698
- }
699
- let methodReqHandler;
700
- switch (method) {
701
- case "GET": {
702
- methodReqHandler = routeModule.onGet;
703
- break;
704
- }
705
- case "POST": {
706
- methodReqHandler = routeModule.onPost;
707
- break;
708
- }
709
- case "PUT": {
710
- methodReqHandler = routeModule.onPut;
711
- break;
712
- }
713
- case "PATCH": {
714
- methodReqHandler = routeModule.onPatch;
715
- break;
716
- }
717
- case "DELETE": {
718
- methodReqHandler = routeModule.onDelete;
719
- break;
720
- }
721
- case "OPTIONS": {
722
- methodReqHandler = routeModule.onOptions;
723
- break;
724
- }
725
- case "HEAD": {
726
- methodReqHandler = routeModule.onHead;
727
- break;
728
- }
729
- }
730
- if (typeof methodReqHandler === "function") {
731
- requestHandlers.push(methodReqHandler);
732
- } else if (Array.isArray(methodReqHandler)) {
733
- requestHandlers.push(...methodReqHandler);
734
- }
185
+ function _resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, collectActions, method, guardPageHandlersForLoader = false) {
186
+ for (let i = 0; i < routeModules.length; i++) {
187
+ const routeModule = routeModules[i];
188
+ const moduleHandlers = getModuleRequestHandlers(routeModule, method);
189
+ const shouldGuardPageHandlers = guardPageHandlersForLoader && i === routeModules.length - 1;
190
+ requestHandlers.push(...shouldGuardPageHandlers ? moduleHandlers.map((handler) => guardPageHandlerForLoader(routeModule, handler)) : moduleHandlers);
735
191
  if (collectActions) {
736
192
  for (const module of Object.values(routeModule)) {
737
193
  if (typeof module === "function") {
@@ -744,7 +200,73 @@ function createResolveRequestHandlers(deps) {
744
200
  }
745
201
  }
746
202
  }
747
- };
203
+ }
204
+ function getModuleRequestHandlers(routeModule, method) {
205
+ const handlers = [];
206
+ addRequestHandlers(handlers, routeModule.onRequest);
207
+ let methodReqHandler;
208
+ switch (method) {
209
+ case "GET": {
210
+ methodReqHandler = routeModule.onGet;
211
+ break;
212
+ }
213
+ case "POST": {
214
+ methodReqHandler = routeModule.onPost;
215
+ break;
216
+ }
217
+ case "PUT": {
218
+ methodReqHandler = routeModule.onPut;
219
+ break;
220
+ }
221
+ case "PATCH": {
222
+ methodReqHandler = routeModule.onPatch;
223
+ break;
224
+ }
225
+ case "DELETE": {
226
+ methodReqHandler = routeModule.onDelete;
227
+ break;
228
+ }
229
+ case "OPTIONS": {
230
+ methodReqHandler = routeModule.onOptions;
231
+ break;
232
+ }
233
+ case "HEAD": {
234
+ methodReqHandler = routeModule.onHead;
235
+ break;
236
+ }
237
+ }
238
+ addRequestHandlers(handlers, methodReqHandler);
239
+ return handlers;
240
+ }
241
+ function addRequestHandlers(handlers, handler) {
242
+ if (typeof handler === "function") {
243
+ handlers.push(handler);
244
+ } else if (Array.isArray(handler)) {
245
+ handlers.push(...handler);
246
+ }
247
+ }
248
+ function guardPageHandlerForLoader(routeModule, handler) {
249
+ return (requestEv) => {
250
+ if (requestEv.sharedMap.has(IsQLoader)) {
251
+ const loaderId = requestEv.sharedMap.get(QLoaderId);
252
+ if (!moduleHasLoader(routeModule, loaderId)) {
253
+ return;
254
+ }
255
+ }
256
+ return handler(requestEv);
257
+ };
258
+ }
259
+ function moduleHasLoader(routeModule, loaderId) {
260
+ if (typeof loaderId !== "string") {
261
+ return false;
262
+ }
263
+ for (const value of Object.values(routeModule)) {
264
+ if (checkBrand(value, "server_loader") && value.__id === loaderId) {
265
+ return true;
266
+ }
267
+ }
268
+ return false;
269
+ }
748
270
  const checkBrand = (obj, brand) => {
749
271
  return obj && typeof obj === "function" && obj.__brand === brand;
750
272
  };
@@ -756,7 +278,6 @@ function createResolveRequestHandlers(deps) {
756
278
  return;
757
279
  }
758
280
  const { method } = requestEv;
759
- const loaders = deps.getRequestLoaders(requestEv);
760
281
  if (isDev && method === "GET") {
761
282
  if (requestEv.query.has(deps.QACTION_KEY)) {
762
283
  console.warn('Seems like you are submitting a Qwik Action via GET request. Qwik Actions should be submitted via POST request.\nMake sure your <form> has method="POST" attribute, like this: <form method="POST">');
@@ -774,66 +295,79 @@ function createResolveRequestHandlers(deps) {
774
295
  throw new Error(`Expected request data for the action id ${selectedActionId} to be an object`);
775
296
  }
776
297
  const result = await runValidators(requestEv, action.__validators, data);
298
+ let actionResult;
777
299
  if (!result.success) {
778
- loaders[selectedActionId] = requestEv.fail(result.status ?? 500, result.error);
300
+ actionResult = requestEv.fail(result.status ?? 500, result.error);
779
301
  } else {
780
302
  const actionResolved = isDev ? await measure(requestEv, action.__qrl.getHash(), () => action.__qrl.call(requestEv, result.data, requestEv)) : await action.__qrl.call(requestEv, result.data, requestEv);
781
303
  if (isDev) {
782
304
  verifySerializable(actionResolved, action.__qrl);
783
305
  }
784
- loaders[selectedActionId] = actionResolved;
306
+ actionResult = actionResolved;
785
307
  }
308
+ requestEv.sharedMap.set("@actionResult", actionResult);
786
309
  }
787
310
  }
788
311
  }
789
312
  };
790
313
  }
791
- function loadersMiddleware(routeLoaders) {
314
+ function loadersMiddleware(routeLoaders, route) {
792
315
  return async (requestEvent) => {
793
316
  const requestEv = requestEvent;
794
317
  if (requestEv.headersSent) {
795
318
  requestEv.exit();
796
319
  return;
797
320
  }
798
- const loaders = deps.getRequestLoaders(requestEv);
799
- const loadersSerializationStrategy = deps.getRequestLoaderSerializationStrategyMap(requestEv);
800
321
  if (routeLoaders.length > 0) {
801
- const resolvedLoadersPromises = routeLoaders.map((loader) => deps.getRouteLoaderPromise(loader, loaders, loadersSerializationStrategy, requestEv));
802
- await Promise.all(resolvedLoadersPromises);
322
+ setLoaderData(requestEv, routeLoaders, route);
323
+ const loaderValues = getRouteLoaderValues(requestEv);
324
+ await Promise.all(routeLoaders.map(async (loader) => {
325
+ loaderValues[loader.__id] = await loadRouteLoader(loader, requestEv);
326
+ }));
803
327
  }
804
328
  };
805
329
  }
330
+ function setLoaderData(requestEv, routeLoaders, route) {
331
+ if (routeLoaders.length === 0) {
332
+ return;
333
+ }
334
+ const routeLoaderCtx = getRouteLoaderCtx(requestEv);
335
+ if (route.$loaderPaths$) {
336
+ Object.assign(routeLoaderCtx.loaderPaths, route.$loaderPaths$);
337
+ }
338
+ setRouteLoaders(requestEv, routeLoaders);
339
+ }
806
340
  function eTagMiddleware(route) {
807
341
  return (requestEv) => {
808
342
  if (requestEv.headersSent) {
809
343
  return;
810
344
  }
811
- if (requestEv.method !== "GET" || requestEv.sharedMap.has(deps.IsQData)) {
345
+ if (requestEv.method !== "GET") {
812
346
  return;
813
347
  }
814
348
  const mods = route.$mods$;
815
- const hasETag = mods.some((m) => {
349
+ const hasCachingConfig = mods.some((m) => {
816
350
  if (!m) {
817
351
  return false;
818
352
  }
819
353
  if (m.routeConfig) {
820
- return typeof m.routeConfig === "function" || m.routeConfig.eTag !== void 0;
354
+ return typeof m.routeConfig === "function" || m.routeConfig.eTag !== void 0 || m.routeConfig.cacheKey !== void 0;
821
355
  }
822
- return m.eTag !== void 0;
356
+ return m.eTag !== void 0 || m.cacheKey !== void 0;
823
357
  });
824
- if (!hasETag) {
358
+ if (!hasCachingConfig) {
825
359
  return;
826
360
  }
827
- const loaders = deps.getRequestLoaders(requestEv);
361
+ const loaderValues = getRouteLoaderValues(requestEv);
828
362
  const getData = (loaderOrAction) => {
829
363
  const id = loaderOrAction.__id;
830
- if (loaderOrAction.__brand === "server_loader" && !(id in loaders)) {
831
- throw new Error("Loader not executed for this request.");
832
- }
833
- if (loaders[id] instanceof Promise) {
834
- throw new Error("Loaders returning a promise cannot be resolved for the eTag function.");
364
+ if (loaderOrAction.__brand === "server_loader") {
365
+ if (!(id in loaderValues)) {
366
+ throw new Error("Loader not executed for this request.");
367
+ }
368
+ return loaderValues[id];
835
369
  }
836
- return loaders[id];
370
+ return requestEv.sharedMap.get(deps.RequestEvSharedActionId) === id ? requestEv.sharedMap.get("@actionResult") : void 0;
837
371
  };
838
372
  const routeLocation = {
839
373
  params: requestEv.params,
@@ -850,32 +384,36 @@ function createResolveRequestHandlers(deps) {
850
384
  resolveValue: getData,
851
385
  ...routeLocation
852
386
  };
853
- const eTag = deps.resolveETag(config.eTag, headProps);
854
- if (!eTag) {
855
- return;
856
- }
857
- requestEv.headers.set("ETag", eTag);
858
- const ifNoneMatch = requestEv.request.headers.get("If-None-Match");
859
- if (ifNoneMatch && (ifNoneMatch === eTag || ifNoneMatch === `W/${eTag}` || `W/${ifNoneMatch}` === eTag)) {
860
- requestEv.status(304);
861
- requestEv.send(304, "");
387
+ const resolvedETag = deps.resolveETag(config.eTag, headProps);
388
+ const normalizedETag = resolvedETag !== null ? normalizeETag(resolvedETag) : "";
389
+ if (normalizedETag && performETagMatch(requestEv, normalizedETag)) {
862
390
  return;
863
391
  }
864
392
  if (deps.MAX_CACHE_SIZE <= 0) {
865
393
  return;
866
394
  }
867
- const cacheKey = deps.resolveCacheKey(config.cacheKey, status, eTag, requestEv.url.pathname);
395
+ const cacheKey = deps.resolveCacheKey(config.cacheKey, deps.defaultSsrCacheKey, requestEv, normalizedETag);
868
396
  if (!cacheKey) {
869
397
  return;
870
398
  }
871
- const cachedHtml = deps.getCachedHtml(cacheKey);
872
- if (cachedHtml) {
399
+ const cached = deps.getCachedSsr(cacheKey);
400
+ if (cached) {
873
401
  requestEv.headers.set("Content-Type", "text/html; charset=utf-8");
874
402
  requestEv.headers.set("X-SSR-Cache", "HIT");
875
- requestEv.send(status, cachedHtml);
403
+ if (!normalizedETag) {
404
+ if (performETagMatch(requestEv, cached.eTag)) {
405
+ return;
406
+ }
407
+ } else {
408
+ setETagHeader(requestEv, cached.eTag);
409
+ }
410
+ requestEv.send(status, cached.body);
876
411
  return;
877
412
  }
878
- requestEv.sharedMap.set(deps.RequestEvETagCacheKey, cacheKey);
413
+ requestEv.sharedMap.set(deps.RequestEvETagCacheKey, {
414
+ key: cacheKey,
415
+ eTag: normalizedETag
416
+ });
879
417
  };
880
418
  }
881
419
  function serverErrorMiddleware(route, renderHandler) {
@@ -886,9 +424,6 @@ function createResolveRequestHandlers(deps) {
886
424
  if (!(e instanceof deps.ServerError) || requestEv.headersSent) {
887
425
  throw e;
888
426
  }
889
- if (requestEv.sharedMap.has(deps.IsQData)) {
890
- throw e;
891
- }
892
427
  const accept = requestEv.request.headers.get("Accept");
893
428
  if (accept && !accept.includes("text/html")) {
894
429
  throw e;
@@ -978,16 +513,15 @@ function createResolveRequestHandlers(deps) {
978
513
  }
979
514
  }
980
515
  function fixTrailingSlash(ev) {
981
- const { basePathname, originalUrl, sharedMap } = ev;
516
+ const { basePathname, originalUrl } = ev;
982
517
  const { pathname, search } = originalUrl;
983
- const isQData = sharedMap.has(deps.IsQData);
984
518
  if (!pathname.startsWith("/") || pathname.startsWith("//")) {
985
519
  return;
986
520
  }
987
- if (!isQData && pathname !== basePathname && !pathname.endsWith(".html")) {
521
+ if (pathname !== basePathname && !pathname.endsWith(".html")) {
988
522
  if (!globalThis.__NO_TRAILING_SLASH__) {
989
523
  if (!pathname.endsWith("/")) {
990
- throw ev.redirect(deps.HttpStatus.MovedPermanently, pathname + "/" + search);
524
+ throw ev.redirect(deps.HttpStatus.MovedPermanently, ensureSlash(pathname) + search);
991
525
  }
992
526
  } else {
993
527
  if (pathname.endsWith("/")) {
@@ -1015,12 +549,9 @@ function createResolveRequestHandlers(deps) {
1015
549
  }
1016
550
  function getPathname(url) {
1017
551
  url = new URL(url);
1018
- if (url.pathname.endsWith(deps.QDATA_JSON)) {
1019
- url.pathname = url.pathname.slice(0, -deps.QDATA_JSON.length);
1020
- }
1021
552
  if (!globalThis.__NO_TRAILING_SLASH__) {
1022
553
  if (!url.pathname.endsWith("/")) {
1023
- url.pathname += "/";
554
+ url.pathname = ensureSlash(url.pathname);
1024
555
  }
1025
556
  } else {
1026
557
  if (url.pathname.endsWith("/")) {
@@ -1057,19 +588,16 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1057
588
  if (requestEv.headersSent) {
1058
589
  return;
1059
590
  }
1060
- if (requestEv.sharedMap.has(deps.IsQData)) {
1061
- return;
1062
- }
1063
591
  const responseHeaders = requestEv.headers;
1064
592
  if (!responseHeaders.has("Content-Type")) {
1065
593
  responseHeaders.set("Content-Type", "text/html; charset=utf-8");
1066
594
  }
1067
- const eTagCacheKey = requestEv.sharedMap.get(deps.RequestEvETagCacheKey);
595
+ const cachePlan = requestEv.sharedMap.get(deps.RequestEvETagCacheKey);
1068
596
  const { readable, writable } = new TextEncoderStream();
1069
597
  const writableStream = requestEv.getWritableStream();
1070
598
  let cacheChunks;
1071
599
  let pipeSource = readable;
1072
- if (eTagCacheKey) {
600
+ if (cachePlan) {
1073
601
  cacheChunks = [];
1074
602
  const capture = new TransformStream({
1075
603
  transform(chunk, controller) {
@@ -1086,29 +614,24 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1086
614
  pipeError = error;
1087
615
  });
1088
616
  const stream = writable.getWriter();
1089
- const status = requestEv.status();
1090
617
  try {
1091
618
  const isStatic = deps.getRequestMode(requestEv) === "static";
1092
619
  const serverData = deps.getQwikRouterServerData(requestEv);
1093
620
  const result = await render({
1094
621
  base: requestEv.basePathname + "build/",
1095
622
  stream,
623
+ streaming: isStatic ? {
624
+ outOfOrder: false
625
+ } : void 0,
1096
626
  serverData,
1097
627
  containerAttributes: {
1098
628
  ["q:render"]: isStatic ? "static" : "",
1099
629
  ...serverData.containerAttributes
1100
630
  }
1101
631
  });
1102
- const qData = {
1103
- loaders: deps.getRequestLoaders(requestEv),
1104
- action: requestEv.sharedMap.get(deps.RequestEvSharedActionId),
1105
- status: status !== 200 ? status : 200,
1106
- href: getPathname(requestEv.url)
1107
- };
1108
632
  if (typeof result.html === "string") {
1109
633
  await stream.write(result.html);
1110
634
  }
1111
- requestEv.sharedMap.set(deps.RequestEvShareQData, qData);
1112
635
  } finally {
1113
636
  await stream.ready;
1114
637
  await stream.close();
@@ -1117,7 +640,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1117
640
  if (pipeError) {
1118
641
  throw pipeError;
1119
642
  }
1120
- if (eTagCacheKey && cacheChunks && cacheChunks.length > 0) {
643
+ if (cachePlan && cacheChunks && cacheChunks.length > 0) {
1121
644
  const totalLength = cacheChunks.reduce((sum, chunk) => sum + chunk.length, 0);
1122
645
  const combined = new Uint8Array(totalLength);
1123
646
  let offset = 0;
@@ -1125,86 +648,16 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
1125
648
  combined.set(chunk, offset);
1126
649
  offset += chunk.length;
1127
650
  }
1128
- deps.setCachedHtml(eTagCacheKey, new TextDecoder().decode(combined));
651
+ const html = new TextDecoder().decode(combined);
652
+ const cachedETag = cachePlan.eTag || hash(html);
653
+ deps.setCachedSsr(cachePlan.key, {
654
+ eTag: cachedETag,
655
+ body: html
656
+ });
1129
657
  }
1130
658
  await writableStream.close();
1131
659
  };
1132
660
  }
1133
- async function handleQDataRedirect(requestEv) {
1134
- try {
1135
- await requestEv.next();
1136
- } catch (err) {
1137
- if (!(err instanceof deps.RedirectMessage)) {
1138
- throw err;
1139
- }
1140
- }
1141
- if (requestEv.headersSent) {
1142
- return;
1143
- }
1144
- const status = requestEv.status();
1145
- const location = requestEv.headers.get("Location");
1146
- const isRedirect = status >= 301 && status <= 308 && location;
1147
- if (isRedirect) {
1148
- const adaptedLocation = makeQDataPath(location);
1149
- if (adaptedLocation) {
1150
- requestEv.headers.set("Location", adaptedLocation);
1151
- requestEv.getWritableStream().close();
1152
- return;
1153
- } else {
1154
- requestEv.status(200);
1155
- requestEv.headers.delete("Location");
1156
- }
1157
- }
1158
- }
1159
- async function renderQData(requestEv) {
1160
- await requestEv.next();
1161
- if (requestEv.headersSent || requestEv.exited) {
1162
- return;
1163
- }
1164
- const status = requestEv.status();
1165
- const redirectLocation = requestEv.headers.get("Location");
1166
- requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
1167
- let loaders = deps.getRequestLoaders(requestEv);
1168
- const selectedLoaderIds = requestEv.query.getAll(deps.QLOADER_KEY);
1169
- const hasCustomLoaders = selectedLoaderIds.length > 0;
1170
- if (hasCustomLoaders) {
1171
- const selectedLoaders = {};
1172
- for (const loaderId of selectedLoaderIds) {
1173
- const loader = loaders[loaderId];
1174
- selectedLoaders[loaderId] = loader;
1175
- }
1176
- loaders = selectedLoaders;
1177
- }
1178
- const qData = hasCustomLoaders ? {
1179
- loaders,
1180
- status: status !== 200 ? status : 200,
1181
- href: getPathname(requestEv.url)
1182
- } : {
1183
- loaders,
1184
- action: requestEv.sharedMap.get(deps.RequestEvSharedActionId),
1185
- status: status !== 200 ? status : 200,
1186
- href: getPathname(requestEv.url),
1187
- redirect: redirectLocation ?? void 0,
1188
- isRewrite: requestEv.sharedMap.get(deps.RequestEvIsRewrite)
1189
- };
1190
- const writer = requestEv.getWritableStream().getWriter();
1191
- const data = await _serialize(qData);
1192
- writer.write(deps.encoder.encode(data));
1193
- requestEv.sharedMap.set(deps.RequestEvShareQData, qData);
1194
- writer.close();
1195
- }
1196
- function makeQDataPath(href) {
1197
- if (href.startsWith("/")) {
1198
- if (!href.includes(deps.QDATA_JSON)) {
1199
- const url = new URL(href, "http://localhost");
1200
- const pathname = url.pathname.endsWith("/") ? url.pathname.slice(0, -1) : url.pathname;
1201
- return pathname + deps.QDATA_JSON + url.search;
1202
- }
1203
- return href;
1204
- } else {
1205
- return void 0;
1206
- }
1207
- }
1208
661
  function now() {
1209
662
  return typeof performance !== "undefined" ? performance.now() : 0;
1210
663
  }
@@ -1254,24 +707,11 @@ function isContentType(headers, ...types) {
1254
707
  return false;
1255
708
  }
1256
709
 
1257
- class ServerError extends Error {
1258
- status;
1259
- data;
1260
- constructor(status, data) {
1261
- super(typeof data === "string" ? data : void 0), this.status = status, this.data = data;
1262
- }
1263
- }
1264
-
1265
710
  const requestHandlers = createResolveRequestHandlers({
1266
711
  QACTION_KEY,
1267
712
  QFN_KEY,
1268
- QLOADER_KEY,
1269
- QDATA_JSON,
1270
- IsQData,
1271
713
  RequestEvETagCacheKey,
1272
714
  RequestEvHttpStatusMessage,
1273
- RequestEvIsRewrite,
1274
- RequestEvShareQData,
1275
715
  RequestEvShareServerTiming,
1276
716
  RequestEvSharedActionId,
1277
717
  RequestRouteName,
@@ -1280,31 +720,22 @@ const requestHandlers = createResolveRequestHandlers({
1280
720
  HttpStatus,
1281
721
  encoder,
1282
722
  isContentType,
1283
- getCachedHtml,
723
+ defaultSsrCacheKey,
724
+ defaultLoaderCacheKey,
725
+ getCachedSsr,
726
+ getCachedLoader,
1284
727
  getQwikRouterServerData,
1285
- getRequestLoaderSerializationStrategyMap,
1286
- getRequestLoaders,
1287
728
  getRequestMode,
1288
- getRouteLoaderPromise,
1289
729
  loadHttpError: () => import('../../chunks/http-error.qwik.mjs'),
1290
730
  MAX_CACHE_SIZE,
1291
731
  resolveCacheKey,
1292
732
  resolveETag,
1293
733
  resolveRouteConfig,
1294
- setCachedHtml
734
+ setCachedSsr,
735
+ setCachedLoader
1295
736
  });
1296
737
  const { renderQwikMiddleware, resolveRequestHandlers} = requestHandlers;
1297
738
 
1298
- let _asyncRequestStore;
1299
- if (isServer) {
1300
- const AsyncLocalStorage = _getAsyncLocalStorage();
1301
- if (AsyncLocalStorage) {
1302
- _asyncRequestStore = new AsyncLocalStorage();
1303
- } else {
1304
- console.warn("\n=====================\n Qwik Router Warning:\n AsyncLocalStorage is not available, continuing without it.\n This impacts concurrent async server calls, where they lose access to the ServerRequestEv object.\n=====================\n\n");
1305
- }
1306
- }
1307
-
1308
739
  function createCacheControl(cacheControl) {
1309
740
  const controls = [];
1310
741
  if (cacheControl === "day") {
@@ -1525,6 +956,7 @@ class RewriteMessage extends AbortMessage {
1525
956
 
1526
957
  const requestEventDeps = {
1527
958
  QDATA_KEY,
959
+ QACTION_KEY,
1528
960
  isPromise,
1529
961
  createCacheControl,
1530
962
  Cookie,
@@ -1532,9 +964,12 @@ const requestEventDeps = {
1532
964
  RedirectMessage,
1533
965
  RewriteMessage,
1534
966
  ServerError,
1535
- getRouteLoaderPromise,
1536
- getRouteMatchPathname,
1537
- IsQData,
967
+ recognizeRequest,
968
+ trimRecognizedInternalPathname,
969
+ IsQLoader,
970
+ IsQAction,
971
+ QLoaderId,
972
+ QActionId,
1538
973
  encoder,
1539
974
  getContentType
1540
975
  };
@@ -1585,7 +1020,7 @@ async function runNextWithDeps(requestEv, rebuildRouteInfo, resolve, deps) {
1585
1020
  }
1586
1021
  return e;
1587
1022
  }
1588
- if (!isDev) {
1023
+ if (!isDev$1) {
1589
1024
  try {
1590
1025
  if (!requestEv.headersSent) {
1591
1026
  requestEv.headers.set("content-type", "text/html; charset=utf-8");
@@ -1646,10 +1081,21 @@ async function getConfig() {
1646
1081
  }
1647
1082
  return qwikRouterConfig;
1648
1083
  }
1649
- async function loadRequestHandlers(qwikRouterConfig2, pathname, method, checkOrigin, renderFn, isInternal) {
1084
+ function getRequestHandlerPathname(serverRequestEv) {
1085
+ const recognized = recognizeRequest(serverRequestEv.url.pathname);
1086
+ if (!recognized) {
1087
+ return serverRequestEv.url.pathname;
1088
+ }
1089
+ const loaderPathname = trimRecognizedInternalPathname(serverRequestEv.url.pathname, recognized);
1090
+ if (recognized.type !== IsQLoader) {
1091
+ return loaderPathname;
1092
+ }
1093
+ return resolveValidInternalFullPathname(loaderPathname, serverRequestEv.request.headers.get(FULLPATH_HEADER)) ?? loaderPathname;
1094
+ }
1095
+ async function loadRequestHandlers(qwikRouterConfig2, pathname, method, checkOrigin, renderFn) {
1650
1096
  const { routes, serverPlugins, cacheModules } = qwikRouterConfig2;
1651
- const loadedRoute = await loadRoute(routes, cacheModules, pathname, isInternal);
1652
- const requestHandlers = resolveRequestHandlers(serverPlugins, loadedRoute, method, checkOrigin, renderQwikMiddleware(renderFn), isInternal);
1097
+ const loadedRoute = await loadRoute(routes, cacheModules, pathname);
1098
+ const requestHandlers = resolveRequestHandlers(serverPlugins, loadedRoute, method, checkOrigin, renderQwikMiddleware(renderFn));
1653
1099
  return {
1654
1100
  loadedRoute,
1655
1101
  requestHandlers
@@ -1658,17 +1104,17 @@ async function loadRequestHandlers(qwikRouterConfig2, pathname, method, checkOri
1658
1104
  async function requestHandler(serverRequestEv, opts) {
1659
1105
  const { render, checkOrigin } = opts;
1660
1106
  const config = await getConfig();
1661
- const { pathname, isInternal } = getRouteMatchPathname(serverRequestEv.url.pathname);
1107
+ const pathname = getRequestHandlerPathname(serverRequestEv);
1662
1108
  if (pathname === "/.well-known" || pathname.startsWith("/.well-known/")) {
1663
1109
  return null;
1664
1110
  }
1665
- const { loadedRoute, requestHandlers } = await loadRequestHandlers(config, pathname, serverRequestEv.request.method, checkOrigin ?? true, render, isInternal);
1111
+ const { loadedRoute, requestHandlers } = await loadRequestHandlers(config, pathname, serverRequestEv.request.method, checkOrigin ?? true, render);
1666
1112
  if (config.fallthrough && loadedRoute.$notFound$) {
1667
1113
  return null;
1668
1114
  }
1669
1115
  const rebuildRouteInfo = async (url) => {
1670
- const { pathname: pathname2 } = getRouteMatchPathname(url.pathname);
1671
- return loadRequestHandlers(config, pathname2, serverRequestEv.request.method, checkOrigin ?? true, render, isInternal);
1116
+ const cleanPathname = trimInternalPathname(url.pathname);
1117
+ return loadRequestHandlers(config, cleanPathname, serverRequestEv.request.method, checkOrigin ?? true, render);
1672
1118
  };
1673
1119
  return runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, config.basePathname);
1674
1120
  }
@@ -1703,12 +1149,10 @@ function isStaticPath(method, url) {
1703
1149
  if (staticPaths.has(p)) {
1704
1150
  return true;
1705
1151
  }
1706
- if (p.endsWith("/q-data.json")) {
1707
- const pWithoutQdata = p.replace(/\/q-data.json$/, "");
1708
- if (staticPaths.has(pWithoutQdata + "/")) {
1709
- return true;
1710
- }
1711
- if (staticPaths.has(pWithoutQdata)) {
1152
+ const loaderMatch = p.match(LOADER_REGEX);
1153
+ if (loaderMatch) {
1154
+ const pWithoutLoader = p.slice(0, p.length - loaderMatch[0].length);
1155
+ if (staticPaths.has(pWithoutLoader + "/") || staticPaths.has(pWithoutLoader)) {
1712
1156
  return true;
1713
1157
  }
1714
1158
  }
@@ -1772,4 +1216,4 @@ class _TextEncoderStream_polyfill {
1772
1216
  }
1773
1217
  }
1774
1218
 
1775
- export { AbortMessage, RedirectMessage, RequestEvShareQData, RewriteMessage, ServerError, _TextEncoderStream_polyfill, _asyncRequestStore, clearSsrCache, getErrorHtml, getNotFound, isStaticPath, mergeHeadersCookies, requestHandler };
1219
+ export { AbortMessage, RedirectMessage, RewriteMessage, ServerError, _TextEncoderStream_polyfill, _asyncRequestStore, getErrorHtml, getNotFound, isStaticPath, mergeHeadersCookies, requestHandler };