@qwik.dev/router 2.0.0-beta.37 → 2.0.0-beta.39
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/cloudflare-pages/vite/index.mjs +2 -2
- package/lib/adapters/shared/vite/index.d.ts +3 -4
- package/lib/adapters/shared/vite/index.mjs +158 -143
- package/lib/chunks/dev-preloaded-route-loader.mjs +3 -0
- package/lib/chunks/fs.mjs +6 -2
- package/lib/chunks/head.qwik.mjs +814 -93
- package/lib/chunks/request-body-limit.mjs +37 -0
- package/lib/chunks/request-path.mjs +2 -2
- package/lib/chunks/routes.mjs +47 -0
- package/lib/chunks/server-error.mjs +19 -0
- package/lib/chunks/system.mjs +2 -1
- package/lib/chunks/use-functions.qwik.mjs +1 -1
- package/lib/chunks/{worker-thread.qwik.mjs → user-response.mjs} +1053 -1749
- package/lib/chunks/worker-thread.mjs +317 -0
- package/lib/index.d.ts +89 -55
- package/lib/index.qwik.mjs +178 -100
- package/lib/middleware/azure-swa/index.mjs +13 -9
- package/lib/middleware/cloudflare-pages/index.mjs +2 -2
- package/lib/middleware/deno/index.d.ts +2 -0
- package/lib/middleware/deno/index.mjs +2 -1
- package/lib/middleware/netlify-edge/index.mjs +2 -2
- package/lib/middleware/node/index.d.ts +9 -1
- package/lib/middleware/node/index.mjs +28 -3
- package/lib/middleware/request-handler/index.d.ts +9 -10
- package/lib/middleware/request-handler/index.mjs +26 -1105
- package/lib/middleware/vercel-edge/index.mjs +2 -2
- package/lib/ssg/index.d.ts +2 -10
- package/lib/ssg/index.mjs +10 -50
- package/lib/vite/index.d.ts +8 -0
- package/lib/vite/index.mjs +406 -117
- package/package.json +5 -4
- package/lib/chunks/action-handler.mjs +0 -782
- package/lib/chunks/deepFreeze.qwik.mjs +0 -608
- package/lib/chunks/error-handler.mjs +0 -57
- package/lib/chunks/not-found-wrapper.qwik.mjs +0 -25
|
@@ -1,1087 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { g as getErrorHtml, m as minimalHtmlResponse } from '../../chunks/error-handler.mjs';
|
|
10
|
-
|
|
11
|
-
var HttpStatus = /* @__PURE__ */ (function(HttpStatus2) {
|
|
12
|
-
HttpStatus2[HttpStatus2["Continue"] = 100] = "Continue";
|
|
13
|
-
HttpStatus2[HttpStatus2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
|
14
|
-
HttpStatus2[HttpStatus2["Processing"] = 102] = "Processing";
|
|
15
|
-
HttpStatus2[HttpStatus2["Ok"] = 200] = "Ok";
|
|
16
|
-
HttpStatus2[HttpStatus2["Created"] = 201] = "Created";
|
|
17
|
-
HttpStatus2[HttpStatus2["Accepted"] = 202] = "Accepted";
|
|
18
|
-
HttpStatus2[HttpStatus2["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
|
19
|
-
HttpStatus2[HttpStatus2["NoContent"] = 204] = "NoContent";
|
|
20
|
-
HttpStatus2[HttpStatus2["ResetContent"] = 205] = "ResetContent";
|
|
21
|
-
HttpStatus2[HttpStatus2["PartialContent"] = 206] = "PartialContent";
|
|
22
|
-
HttpStatus2[HttpStatus2["MultiStatus"] = 207] = "MultiStatus";
|
|
23
|
-
HttpStatus2[HttpStatus2["AlreadyReported"] = 208] = "AlreadyReported";
|
|
24
|
-
HttpStatus2[HttpStatus2["ImUsed"] = 226] = "ImUsed";
|
|
25
|
-
HttpStatus2[HttpStatus2["MultipleChoices"] = 300] = "MultipleChoices";
|
|
26
|
-
HttpStatus2[HttpStatus2["MovedPermanently"] = 301] = "MovedPermanently";
|
|
27
|
-
HttpStatus2[HttpStatus2["Found"] = 302] = "Found";
|
|
28
|
-
HttpStatus2[HttpStatus2["SeeOther"] = 303] = "SeeOther";
|
|
29
|
-
HttpStatus2[HttpStatus2["NotModified"] = 304] = "NotModified";
|
|
30
|
-
HttpStatus2[HttpStatus2["UseProxy"] = 305] = "UseProxy";
|
|
31
|
-
HttpStatus2[HttpStatus2["SwitchProxy"] = 306] = "SwitchProxy";
|
|
32
|
-
HttpStatus2[HttpStatus2["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
|
33
|
-
HttpStatus2[HttpStatus2["PermanentRedirect"] = 308] = "PermanentRedirect";
|
|
34
|
-
HttpStatus2[HttpStatus2["BadRequest"] = 400] = "BadRequest";
|
|
35
|
-
HttpStatus2[HttpStatus2["Unauthorized"] = 401] = "Unauthorized";
|
|
36
|
-
HttpStatus2[HttpStatus2["PaymentRequired"] = 402] = "PaymentRequired";
|
|
37
|
-
HttpStatus2[HttpStatus2["Forbidden"] = 403] = "Forbidden";
|
|
38
|
-
HttpStatus2[HttpStatus2["NotFound"] = 404] = "NotFound";
|
|
39
|
-
HttpStatus2[HttpStatus2["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
|
40
|
-
HttpStatus2[HttpStatus2["NotAcceptable"] = 406] = "NotAcceptable";
|
|
41
|
-
HttpStatus2[HttpStatus2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
|
42
|
-
HttpStatus2[HttpStatus2["RequestTimeout"] = 408] = "RequestTimeout";
|
|
43
|
-
HttpStatus2[HttpStatus2["Conflict"] = 409] = "Conflict";
|
|
44
|
-
HttpStatus2[HttpStatus2["Gone"] = 410] = "Gone";
|
|
45
|
-
HttpStatus2[HttpStatus2["LengthRequired"] = 411] = "LengthRequired";
|
|
46
|
-
HttpStatus2[HttpStatus2["PreconditionFailed"] = 412] = "PreconditionFailed";
|
|
47
|
-
HttpStatus2[HttpStatus2["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
|
48
|
-
HttpStatus2[HttpStatus2["UriTooLong"] = 414] = "UriTooLong";
|
|
49
|
-
HttpStatus2[HttpStatus2["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
|
50
|
-
HttpStatus2[HttpStatus2["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
|
51
|
-
HttpStatus2[HttpStatus2["ExpectationFailed"] = 417] = "ExpectationFailed";
|
|
52
|
-
HttpStatus2[HttpStatus2["IAmATeapot"] = 418] = "IAmATeapot";
|
|
53
|
-
HttpStatus2[HttpStatus2["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
|
54
|
-
HttpStatus2[HttpStatus2["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
|
55
|
-
HttpStatus2[HttpStatus2["Locked"] = 423] = "Locked";
|
|
56
|
-
HttpStatus2[HttpStatus2["FailedDependency"] = 424] = "FailedDependency";
|
|
57
|
-
HttpStatus2[HttpStatus2["UpgradeRequired"] = 426] = "UpgradeRequired";
|
|
58
|
-
HttpStatus2[HttpStatus2["PreconditionRequired"] = 428] = "PreconditionRequired";
|
|
59
|
-
HttpStatus2[HttpStatus2["TooManyRequests"] = 429] = "TooManyRequests";
|
|
60
|
-
HttpStatus2[HttpStatus2["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
|
61
|
-
HttpStatus2[HttpStatus2["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
|
62
|
-
HttpStatus2[HttpStatus2["InternalServerError"] = 500] = "InternalServerError";
|
|
63
|
-
HttpStatus2[HttpStatus2["NotImplemented"] = 501] = "NotImplemented";
|
|
64
|
-
HttpStatus2[HttpStatus2["BadGateway"] = 502] = "BadGateway";
|
|
65
|
-
HttpStatus2[HttpStatus2["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
|
66
|
-
HttpStatus2[HttpStatus2["GatewayTimeout"] = 504] = "GatewayTimeout";
|
|
67
|
-
HttpStatus2[HttpStatus2["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
|
|
68
|
-
HttpStatus2[HttpStatus2["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
|
69
|
-
HttpStatus2[HttpStatus2["InsufficientStorage"] = 507] = "InsufficientStorage";
|
|
70
|
-
HttpStatus2[HttpStatus2["LoopDetected"] = 508] = "LoopDetected";
|
|
71
|
-
HttpStatus2[HttpStatus2["NotExtended"] = 510] = "NotExtended";
|
|
72
|
-
HttpStatus2[HttpStatus2["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
|
73
|
-
return HttpStatus2;
|
|
74
|
-
})({});
|
|
75
|
-
|
|
76
|
-
function getQwikRouterServerDataWithDeps(deps, requestEv) {
|
|
77
|
-
const { params, request, status, locale, originalUrl } = requestEv;
|
|
78
|
-
const requestHeaders = {};
|
|
79
|
-
request.headers.forEach((value, key) => requestHeaders[key] = value);
|
|
80
|
-
const action = requestEv.sharedMap.get(deps.RequestEvSharedActionId);
|
|
81
|
-
const actionResult = requestEv.sharedMap.get("@actionResult");
|
|
82
|
-
const formData = requestEv.sharedMap.get(deps.RequestEvSharedActionFormData);
|
|
83
|
-
const routeName = requestEv.sharedMap.get(deps.RequestRouteName);
|
|
84
|
-
const nonce = requestEv.sharedMap.get(deps.RequestEvSharedNonce);
|
|
85
|
-
const headers = requestEv.request.headers;
|
|
86
|
-
const reconstructedUrl = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
|
|
87
|
-
const host = headers.get("X-Forwarded-Host");
|
|
88
|
-
const protocol = headers.get("X-Forwarded-Proto");
|
|
89
|
-
if (host) {
|
|
90
|
-
reconstructedUrl.port = "";
|
|
91
|
-
reconstructedUrl.host = host;
|
|
92
|
-
}
|
|
93
|
-
if (protocol) {
|
|
94
|
-
reconstructedUrl.protocol = protocol;
|
|
95
|
-
}
|
|
96
|
-
const routeLoaderCtx = getRouteLoaderCtx(requestEv);
|
|
97
|
-
const loaderValues = getRouteLoaderValues(requestEv);
|
|
98
|
-
return {
|
|
99
|
-
url: reconstructedUrl.href,
|
|
100
|
-
requestHeaders,
|
|
101
|
-
renderMode: deps.getRequestMode(requestEv),
|
|
102
|
-
locale: locale(),
|
|
103
|
-
nonce,
|
|
104
|
-
containerAttributes: {
|
|
105
|
-
[deps.Q_ROUTE]: routeName
|
|
106
|
-
},
|
|
107
|
-
qwikrouter: {
|
|
108
|
-
routeName,
|
|
109
|
-
ev: requestEv,
|
|
110
|
-
params: {
|
|
111
|
-
...params
|
|
112
|
-
},
|
|
113
|
-
loadedRoute: deps.getRequestRoute(requestEv),
|
|
114
|
-
routeLoaderCtx,
|
|
115
|
-
loaderValues,
|
|
116
|
-
response: {
|
|
117
|
-
status: status(),
|
|
118
|
-
statusMessage: requestEv.sharedMap.get(deps.RequestEvHttpStatusMessage),
|
|
119
|
-
action,
|
|
120
|
-
actionResult,
|
|
121
|
-
formData
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const responsePageDeps = {
|
|
128
|
-
Q_ROUTE,
|
|
129
|
-
RequestEvHttpStatusMessage,
|
|
130
|
-
RequestEvSharedActionFormData,
|
|
131
|
-
RequestEvSharedActionId,
|
|
132
|
-
RequestEvSharedNonce,
|
|
133
|
-
RequestRouteName,
|
|
134
|
-
getRequestMode,
|
|
135
|
-
getRequestRoute
|
|
136
|
-
};
|
|
137
|
-
function getQwikRouterServerData(...args) {
|
|
138
|
-
return getQwikRouterServerDataWithDeps(responsePageDeps, ...args);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function createResolveRequestHandlers(deps) {
|
|
142
|
-
const resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderHandler) => {
|
|
143
|
-
const routeLoaders = [];
|
|
144
|
-
const routeActions = [];
|
|
145
|
-
const requestHandlers = [];
|
|
146
|
-
const isPageRoute = !!isLastModulePageRoute(route.$mods$);
|
|
147
|
-
if (isPageRoute) {
|
|
148
|
-
requestHandlers.push(jsonRequestWrapper());
|
|
149
|
-
requestHandlers.push(serverErrorMiddleware(route, renderHandler));
|
|
150
|
-
}
|
|
151
|
-
if (serverPlugins) {
|
|
152
|
-
_resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, serverPlugins, isPageRoute, method);
|
|
153
|
-
}
|
|
154
|
-
const routeModules = route.$mods$;
|
|
155
|
-
_resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, isPageRoute, method, isPageRoute);
|
|
156
|
-
const routeName = route.$routeName$;
|
|
157
|
-
if (checkOrigin && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
|
|
158
|
-
if (checkOrigin === "lax-proto") {
|
|
159
|
-
requestHandlers.unshift(csrfLaxProtoCheckMiddleware);
|
|
160
|
-
} else {
|
|
161
|
-
requestHandlers.unshift(csrfCheckMiddleware);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
if (isPageRoute) {
|
|
165
|
-
requestHandlers.push(loaderHandler(routeLoaders, route.$loaderPaths$));
|
|
166
|
-
requestHandlers.push(actionHandler(routeActions));
|
|
167
|
-
if (method === "POST" || method === "GET") {
|
|
168
|
-
requestHandlers.push(runServerFunction);
|
|
169
|
-
}
|
|
170
|
-
if (!route.$notFound$) {
|
|
171
|
-
requestHandlers.push(fixTrailingSlash);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (isPageRoute) {
|
|
175
|
-
requestHandlers.push((ev) => {
|
|
176
|
-
ev.sharedMap.set(deps.RequestRouteName, routeName);
|
|
177
|
-
});
|
|
178
|
-
requestHandlers.push(actionsMiddleware(routeActions));
|
|
179
|
-
requestHandlers.push(loadersMiddleware(routeLoaders, route));
|
|
180
|
-
requestHandlers.push(eTagMiddleware(route));
|
|
181
|
-
requestHandlers.push(renderHandler);
|
|
182
|
-
}
|
|
183
|
-
return requestHandlers;
|
|
184
|
-
};
|
|
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);
|
|
191
|
-
if (collectActions) {
|
|
192
|
-
for (const module of Object.values(routeModule)) {
|
|
193
|
-
if (typeof module === "function") {
|
|
194
|
-
if (module.__brand === "server_loader") {
|
|
195
|
-
routeLoaders.push(module);
|
|
196
|
-
} else if (module.__brand === "server_action") {
|
|
197
|
-
routeActions.push(module);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
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
|
-
}
|
|
270
|
-
const checkBrand = (obj, brand) => {
|
|
271
|
-
return obj && typeof obj === "function" && obj.__brand === brand;
|
|
272
|
-
};
|
|
273
|
-
function actionsMiddleware(routeActions) {
|
|
274
|
-
return async (requestEvent) => {
|
|
275
|
-
const requestEv = requestEvent;
|
|
276
|
-
if (requestEv.headersSent) {
|
|
277
|
-
requestEv.exit();
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
const { method } = requestEv;
|
|
281
|
-
if (isDev && method === "GET") {
|
|
282
|
-
if (requestEv.query.has(deps.QACTION_KEY)) {
|
|
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">');
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
if (method === "POST") {
|
|
287
|
-
const selectedActionId = requestEv.query.get(deps.QACTION_KEY);
|
|
288
|
-
if (selectedActionId) {
|
|
289
|
-
const serverActionsMap = globalThis._qwikActionsMap;
|
|
290
|
-
const action = routeActions.find((action2) => action2.__id === selectedActionId) ?? serverActionsMap?.get(selectedActionId);
|
|
291
|
-
if (action) {
|
|
292
|
-
requestEv.sharedMap.set(deps.RequestEvSharedActionId, selectedActionId);
|
|
293
|
-
const data = await requestEv.parseBody();
|
|
294
|
-
if (!data || typeof data !== "object") {
|
|
295
|
-
throw new Error(`Expected request data for the action id ${selectedActionId} to be an object`);
|
|
296
|
-
}
|
|
297
|
-
const result = await runValidators(requestEv, action.__validators, data);
|
|
298
|
-
let actionResult;
|
|
299
|
-
if (!result.success) {
|
|
300
|
-
actionResult = requestEv.fail(result.status ?? 500, result.error);
|
|
301
|
-
} else {
|
|
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);
|
|
303
|
-
if (isDev) {
|
|
304
|
-
verifySerializable(actionResolved, action.__qrl);
|
|
305
|
-
}
|
|
306
|
-
actionResult = actionResolved;
|
|
307
|
-
}
|
|
308
|
-
requestEv.sharedMap.set("@actionResult", actionResult);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
function loadersMiddleware(routeLoaders, route) {
|
|
315
|
-
return async (requestEvent) => {
|
|
316
|
-
const requestEv = requestEvent;
|
|
317
|
-
if (requestEv.headersSent) {
|
|
318
|
-
requestEv.exit();
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (routeLoaders.length > 0) {
|
|
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
|
-
}));
|
|
327
|
-
}
|
|
328
|
-
};
|
|
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
|
-
}
|
|
340
|
-
function eTagMiddleware(route) {
|
|
341
|
-
return (requestEv) => {
|
|
342
|
-
if (requestEv.headersSent) {
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
if (requestEv.method !== "GET") {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const mods = route.$mods$;
|
|
349
|
-
const hasCachingConfig = mods.some((m) => {
|
|
350
|
-
if (!m) {
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
if (m.routeConfig) {
|
|
354
|
-
return typeof m.routeConfig === "function" || m.routeConfig.eTag !== void 0 || m.routeConfig.cacheKey !== void 0;
|
|
355
|
-
}
|
|
356
|
-
return m.eTag !== void 0 || m.cacheKey !== void 0;
|
|
357
|
-
});
|
|
358
|
-
if (!hasCachingConfig) {
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
const loaderValues = getRouteLoaderValues(requestEv);
|
|
362
|
-
const getData = (loaderOrAction) => {
|
|
363
|
-
const id = loaderOrAction.__id;
|
|
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];
|
|
369
|
-
}
|
|
370
|
-
return requestEv.sharedMap.get(deps.RequestEvSharedActionId) === id ? requestEv.sharedMap.get("@actionResult") : void 0;
|
|
371
|
-
};
|
|
372
|
-
const routeLocation = {
|
|
373
|
-
params: requestEv.params,
|
|
374
|
-
url: requestEv.url,
|
|
375
|
-
isNavigating: false,
|
|
376
|
-
prevUrl: void 0
|
|
377
|
-
};
|
|
378
|
-
const status = requestEv.status();
|
|
379
|
-
const config = deps.resolveRouteConfig(getData, routeLocation, mods, "", status);
|
|
380
|
-
const headProps = {
|
|
381
|
-
head: config.head,
|
|
382
|
-
status,
|
|
383
|
-
withLocale: (fn) => fn(),
|
|
384
|
-
resolveValue: getData,
|
|
385
|
-
...routeLocation
|
|
386
|
-
};
|
|
387
|
-
const resolvedETag = deps.resolveETag(config.eTag, headProps);
|
|
388
|
-
const normalizedETag = resolvedETag !== null ? normalizeETag(resolvedETag) : "";
|
|
389
|
-
if (normalizedETag && performETagMatch(requestEv, normalizedETag)) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
if (deps.MAX_CACHE_SIZE <= 0) {
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
const cacheKey = deps.resolveCacheKey(config.cacheKey, deps.defaultSsrCacheKey, requestEv, normalizedETag);
|
|
396
|
-
if (!cacheKey) {
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
const cached = deps.getCachedSsr(cacheKey);
|
|
400
|
-
if (cached) {
|
|
401
|
-
requestEv.headers.set("Content-Type", "text/html; charset=utf-8");
|
|
402
|
-
requestEv.headers.set("X-SSR-Cache", "HIT");
|
|
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);
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
requestEv.sharedMap.set(deps.RequestEvETagCacheKey, {
|
|
414
|
-
key: cacheKey,
|
|
415
|
-
eTag: normalizedETag
|
|
416
|
-
});
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
function serverErrorMiddleware(route, renderHandler) {
|
|
420
|
-
return async (requestEv) => {
|
|
421
|
-
try {
|
|
422
|
-
await requestEv.next();
|
|
423
|
-
} catch (e) {
|
|
424
|
-
if (!(e instanceof deps.ServerError) || requestEv.headersSent) {
|
|
425
|
-
throw e;
|
|
426
|
-
}
|
|
427
|
-
const accept = requestEv.request.headers.get("Accept");
|
|
428
|
-
if (accept && !accept.includes("text/html")) {
|
|
429
|
-
throw e;
|
|
430
|
-
}
|
|
431
|
-
const status = e.status;
|
|
432
|
-
requestEv.status(status);
|
|
433
|
-
const errorLoader = route.$errorLoader$;
|
|
434
|
-
const errorModule = errorLoader ? await errorLoader() : await deps.loadHttpError();
|
|
435
|
-
route.$mods$ = [
|
|
436
|
-
errorModule
|
|
437
|
-
];
|
|
438
|
-
requestEv.sharedMap.set(deps.RequestEvHttpStatusMessage, typeof e.data === "string" ? e.data : "Server Error");
|
|
439
|
-
await renderHandler(requestEv);
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
async function runValidators(requestEv, validators, data) {
|
|
444
|
-
let lastResult = {
|
|
445
|
-
success: true,
|
|
446
|
-
data
|
|
447
|
-
};
|
|
448
|
-
if (validators) {
|
|
449
|
-
for (const validator of validators) {
|
|
450
|
-
if (isDev) {
|
|
451
|
-
lastResult = await measure(requestEv, `validator$`, () => validator.validate(requestEv, data));
|
|
452
|
-
} else {
|
|
453
|
-
lastResult = await validator.validate(requestEv, data);
|
|
454
|
-
}
|
|
455
|
-
if (!lastResult.success) {
|
|
456
|
-
return lastResult;
|
|
457
|
-
} else {
|
|
458
|
-
data = lastResult.data;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
return lastResult;
|
|
463
|
-
}
|
|
464
|
-
function isAsyncIterator(obj) {
|
|
465
|
-
return obj ? typeof obj === "object" && Symbol.asyncIterator in obj : false;
|
|
466
|
-
}
|
|
467
|
-
async function runServerFunction(ev) {
|
|
468
|
-
const serverFnHash = ev.query.get(deps.QFN_KEY);
|
|
469
|
-
if (serverFnHash && ev.request.headers.get("X-QRL") === serverFnHash && ev.request.headers.get("Content-Type") === "application/qwik-json") {
|
|
470
|
-
ev.exit();
|
|
471
|
-
const data = await ev.parseBody();
|
|
472
|
-
if (!Array.isArray(data) || !(Array.isArray(data[0]) || data[0] === void 0)) {
|
|
473
|
-
throw ev.error(500, "Invalid request");
|
|
474
|
-
}
|
|
475
|
-
const qrl = inlinedQrl(null, serverFnHash, data.slice(1));
|
|
476
|
-
let result;
|
|
477
|
-
try {
|
|
478
|
-
if (isDev) {
|
|
479
|
-
result = await measure(ev, `server_${serverFnHash}`, () => qrl.apply(ev, data[0]));
|
|
480
|
-
} else {
|
|
481
|
-
result = await qrl.apply(ev, data[0]);
|
|
482
|
-
}
|
|
483
|
-
} catch (err) {
|
|
484
|
-
if (err instanceof deps.ServerError) {
|
|
485
|
-
throw ev.error(err.status, err.data);
|
|
486
|
-
}
|
|
487
|
-
console.error(`Server function ${serverFnHash} failed:`, err);
|
|
488
|
-
throw ev.error(500, "Invalid request");
|
|
489
|
-
}
|
|
490
|
-
if (isAsyncIterator(result)) {
|
|
491
|
-
ev.headers.set("Content-Type", "text/qwik-json-stream");
|
|
492
|
-
const writable = ev.getWritableStream();
|
|
493
|
-
const stream = writable.getWriter();
|
|
494
|
-
for await (const item of result) {
|
|
495
|
-
if (isDev) {
|
|
496
|
-
verifySerializable(item, qrl);
|
|
497
|
-
}
|
|
498
|
-
const message = await _serialize(item);
|
|
499
|
-
if (ev.signal.aborted) {
|
|
500
|
-
break;
|
|
501
|
-
}
|
|
502
|
-
await stream.write(deps.encoder.encode(`${message}
|
|
503
|
-
`));
|
|
504
|
-
}
|
|
505
|
-
stream.close();
|
|
506
|
-
} else {
|
|
507
|
-
verifySerializable(result, qrl);
|
|
508
|
-
ev.headers.set("Content-Type", "application/qwik-json");
|
|
509
|
-
const message = await _serialize(result);
|
|
510
|
-
ev.send(200, message);
|
|
511
|
-
}
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
function fixTrailingSlash(ev) {
|
|
516
|
-
const { basePathname, originalUrl } = ev;
|
|
517
|
-
const { pathname, search } = originalUrl;
|
|
518
|
-
if (!pathname.startsWith("/") || pathname.startsWith("//")) {
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
if (pathname !== basePathname && !pathname.endsWith(".html")) {
|
|
522
|
-
if (!globalThis.__NO_TRAILING_SLASH__) {
|
|
523
|
-
if (!pathname.endsWith("/")) {
|
|
524
|
-
throw ev.redirect(deps.HttpStatus.MovedPermanently, ensureSlash(pathname) + search);
|
|
525
|
-
}
|
|
526
|
-
} else {
|
|
527
|
-
if (pathname.endsWith("/")) {
|
|
528
|
-
throw ev.redirect(deps.HttpStatus.MovedPermanently, pathname.slice(0, pathname.length - 1) + search);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
function verifySerializable(data, qrl) {
|
|
534
|
-
try {
|
|
535
|
-
_verifySerializable(data, void 0);
|
|
536
|
-
} catch (e) {
|
|
537
|
-
if (e instanceof Error && qrl.dev) {
|
|
538
|
-
e.loc = qrl.dev;
|
|
539
|
-
}
|
|
540
|
-
throw e;
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
const isQrl = (value) => {
|
|
544
|
-
return typeof value === "function" && typeof value.getSymbol === "function";
|
|
545
|
-
};
|
|
546
|
-
function isLastModulePageRoute(routeModules) {
|
|
547
|
-
const lastRouteModule = routeModules[routeModules.length - 1];
|
|
548
|
-
return lastRouteModule && typeof lastRouteModule.default === "function";
|
|
549
|
-
}
|
|
550
|
-
function getPathname(url) {
|
|
551
|
-
url = new URL(url);
|
|
552
|
-
if (!globalThis.__NO_TRAILING_SLASH__) {
|
|
553
|
-
if (!url.pathname.endsWith("/")) {
|
|
554
|
-
url.pathname = ensureSlash(url.pathname);
|
|
555
|
-
}
|
|
556
|
-
} else {
|
|
557
|
-
if (url.pathname.endsWith("/")) {
|
|
558
|
-
url.pathname = url.pathname.slice(0, -1);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
const search = url.search.slice(1).replaceAll(/&?q(action|data|func|loaders)=[^&]+/g, "");
|
|
562
|
-
return `${url.pathname}${search ? `?${search}` : ""}${url.hash}`;
|
|
563
|
-
}
|
|
564
|
-
function csrfLaxProtoCheckMiddleware(requestEv) {
|
|
565
|
-
checkCSRF(requestEv, "lax-proto");
|
|
566
|
-
}
|
|
567
|
-
function csrfCheckMiddleware(requestEv) {
|
|
568
|
-
checkCSRF(requestEv);
|
|
569
|
-
}
|
|
570
|
-
function checkCSRF(requestEv, laxProto) {
|
|
571
|
-
const contentType = requestEv.request.headers.get("content-type");
|
|
572
|
-
const isSimpleRequest = !contentType || deps.isContentType(requestEv.request.headers, "application/x-www-form-urlencoded", "multipart/form-data", "text/plain");
|
|
573
|
-
if (isSimpleRequest) {
|
|
574
|
-
const inputOrigin = requestEv.request.headers.get("origin");
|
|
575
|
-
const origin = requestEv.url.origin;
|
|
576
|
-
let forbidden = inputOrigin !== origin;
|
|
577
|
-
if (forbidden && laxProto && inputOrigin?.replace(/^http(s)?/g, "") === origin.replace(/^http(s)?/g, "")) {
|
|
578
|
-
forbidden = false;
|
|
579
|
-
}
|
|
580
|
-
if (forbidden) {
|
|
581
|
-
throw requestEv.error(403, `CSRF check failed. Cross-site ${requestEv.method} form submissions are forbidden.
|
|
582
|
-
The request origin "${inputOrigin}" does not match the server origin "${origin}".`);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
function renderQwikMiddleware(render) {
|
|
587
|
-
return async (requestEv) => {
|
|
588
|
-
if (requestEv.headersSent) {
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
const responseHeaders = requestEv.headers;
|
|
592
|
-
if (!responseHeaders.has("Content-Type")) {
|
|
593
|
-
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
|
|
594
|
-
}
|
|
595
|
-
const cachePlan = requestEv.sharedMap.get(deps.RequestEvETagCacheKey);
|
|
596
|
-
const { readable, writable } = new TextEncoderStream();
|
|
597
|
-
const writableStream = requestEv.getWritableStream();
|
|
598
|
-
let cacheChunks;
|
|
599
|
-
let pipeSource = readable;
|
|
600
|
-
if (cachePlan) {
|
|
601
|
-
cacheChunks = [];
|
|
602
|
-
const capture = new TransformStream({
|
|
603
|
-
transform(chunk, controller) {
|
|
604
|
-
cacheChunks.push(chunk);
|
|
605
|
-
controller.enqueue(chunk);
|
|
606
|
-
}
|
|
607
|
-
});
|
|
608
|
-
pipeSource = readable.pipeThrough(capture);
|
|
609
|
-
}
|
|
610
|
-
let pipeError;
|
|
611
|
-
const pipe = pipeSource.pipeTo(writableStream, {
|
|
612
|
-
preventClose: true
|
|
613
|
-
}).catch((error) => {
|
|
614
|
-
pipeError = error;
|
|
615
|
-
});
|
|
616
|
-
const stream = writable.getWriter();
|
|
617
|
-
try {
|
|
618
|
-
const isStatic = deps.getRequestMode(requestEv) === "static";
|
|
619
|
-
const serverData = deps.getQwikRouterServerData(requestEv);
|
|
620
|
-
const result = await render({
|
|
621
|
-
base: requestEv.basePathname + "build/",
|
|
622
|
-
stream,
|
|
623
|
-
streaming: isStatic ? {
|
|
624
|
-
outOfOrder: false
|
|
625
|
-
} : void 0,
|
|
626
|
-
serverData,
|
|
627
|
-
containerAttributes: {
|
|
628
|
-
["q:render"]: isStatic ? "static" : "",
|
|
629
|
-
...serverData.containerAttributes
|
|
630
|
-
}
|
|
631
|
-
});
|
|
632
|
-
if (typeof result.html === "string") {
|
|
633
|
-
await stream.write(result.html);
|
|
634
|
-
}
|
|
635
|
-
} finally {
|
|
636
|
-
await stream.ready;
|
|
637
|
-
await stream.close();
|
|
638
|
-
await pipe;
|
|
639
|
-
}
|
|
640
|
-
if (pipeError) {
|
|
641
|
-
throw pipeError;
|
|
642
|
-
}
|
|
643
|
-
if (cachePlan && cacheChunks && cacheChunks.length > 0) {
|
|
644
|
-
const totalLength = cacheChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
645
|
-
const combined = new Uint8Array(totalLength);
|
|
646
|
-
let offset = 0;
|
|
647
|
-
for (const chunk of cacheChunks) {
|
|
648
|
-
combined.set(chunk, offset);
|
|
649
|
-
offset += chunk.length;
|
|
650
|
-
}
|
|
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
|
-
});
|
|
657
|
-
}
|
|
658
|
-
await writableStream.close();
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
function now() {
|
|
662
|
-
return typeof performance !== "undefined" ? performance.now() : 0;
|
|
663
|
-
}
|
|
664
|
-
async function measure(requestEv, name, fn) {
|
|
665
|
-
const start = now();
|
|
666
|
-
try {
|
|
667
|
-
return await fn();
|
|
668
|
-
} finally {
|
|
669
|
-
const duration = now() - start;
|
|
670
|
-
let measurements = requestEv.sharedMap.get(deps.RequestEvShareServerTiming);
|
|
671
|
-
if (!measurements) {
|
|
672
|
-
requestEv.sharedMap.set(deps.RequestEvShareServerTiming, measurements = []);
|
|
673
|
-
}
|
|
674
|
-
measurements.push([
|
|
675
|
-
name,
|
|
676
|
-
duration
|
|
677
|
-
]);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
return {
|
|
681
|
-
actionsMiddleware,
|
|
682
|
-
checkBrand,
|
|
683
|
-
checkCSRF,
|
|
684
|
-
fixTrailingSlash,
|
|
685
|
-
getPathname,
|
|
686
|
-
isLastModulePageRoute,
|
|
687
|
-
isQrl,
|
|
688
|
-
loadersMiddleware,
|
|
689
|
-
measure,
|
|
690
|
-
renderQwikMiddleware,
|
|
691
|
-
resolveRequestHandlers,
|
|
692
|
-
verifySerializable
|
|
693
|
-
};
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
const encoder = /* @__PURE__ */ new TextEncoder();
|
|
697
|
-
function getContentType(headers) {
|
|
698
|
-
return (headers.get("content-type")?.split(/[;,]/, 1)[0].trim() ?? "").toLowerCase();
|
|
699
|
-
}
|
|
700
|
-
function isContentType(headers, ...types) {
|
|
701
|
-
const type = getContentType(headers);
|
|
702
|
-
for (let i = 0; i < types.length; i++) {
|
|
703
|
-
if (types[i].toLowerCase() === type) {
|
|
704
|
-
return true;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
return false;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
const requestHandlers = createResolveRequestHandlers({
|
|
711
|
-
QACTION_KEY,
|
|
712
|
-
QFN_KEY,
|
|
713
|
-
RequestEvETagCacheKey,
|
|
714
|
-
RequestEvHttpStatusMessage,
|
|
715
|
-
RequestEvShareServerTiming,
|
|
716
|
-
RequestEvSharedActionId,
|
|
717
|
-
RequestRouteName,
|
|
718
|
-
RedirectMessage,
|
|
719
|
-
ServerError,
|
|
720
|
-
HttpStatus,
|
|
721
|
-
encoder,
|
|
722
|
-
isContentType,
|
|
723
|
-
defaultSsrCacheKey,
|
|
724
|
-
defaultLoaderCacheKey,
|
|
725
|
-
getCachedSsr,
|
|
726
|
-
getCachedLoader,
|
|
727
|
-
getQwikRouterServerData,
|
|
728
|
-
getRequestMode,
|
|
729
|
-
loadHttpError: () => import('../../chunks/http-error.qwik.mjs'),
|
|
730
|
-
MAX_CACHE_SIZE,
|
|
731
|
-
resolveCacheKey,
|
|
732
|
-
resolveETag,
|
|
733
|
-
resolveRouteConfig,
|
|
734
|
-
setCachedSsr,
|
|
735
|
-
setCachedLoader
|
|
736
|
-
});
|
|
737
|
-
const { renderQwikMiddleware, resolveRequestHandlers} = requestHandlers;
|
|
738
|
-
|
|
739
|
-
function createCacheControl(cacheControl) {
|
|
740
|
-
const controls = [];
|
|
741
|
-
if (cacheControl === "day") {
|
|
742
|
-
cacheControl = 60 * 60 * 24;
|
|
743
|
-
} else if (cacheControl === "week") {
|
|
744
|
-
cacheControl = 60 * 60 * 24 * 7;
|
|
745
|
-
} else if (cacheControl === "month") {
|
|
746
|
-
cacheControl = 60 * 60 * 24 * 30;
|
|
747
|
-
} else if (cacheControl === "year") {
|
|
748
|
-
cacheControl = 60 * 60 * 24 * 365;
|
|
749
|
-
} else if (cacheControl === "private") {
|
|
750
|
-
cacheControl = {
|
|
751
|
-
private: true,
|
|
752
|
-
noCache: true
|
|
753
|
-
};
|
|
754
|
-
} else if (cacheControl === "immutable") {
|
|
755
|
-
cacheControl = {
|
|
756
|
-
public: true,
|
|
757
|
-
immutable: true,
|
|
758
|
-
maxAge: 60 * 60 * 24 * 365
|
|
759
|
-
};
|
|
760
|
-
} else if (cacheControl === "no-cache") {
|
|
761
|
-
cacheControl = {
|
|
762
|
-
noCache: true
|
|
763
|
-
};
|
|
764
|
-
}
|
|
765
|
-
if (typeof cacheControl === "number") {
|
|
766
|
-
cacheControl = {
|
|
767
|
-
maxAge: cacheControl,
|
|
768
|
-
sMaxAge: cacheControl
|
|
769
|
-
};
|
|
770
|
-
}
|
|
771
|
-
if (cacheControl.immutable) {
|
|
772
|
-
controls.push("immutable");
|
|
773
|
-
}
|
|
774
|
-
if (cacheControl.maxAge) {
|
|
775
|
-
controls.push(`max-age=${cacheControl.maxAge}`);
|
|
776
|
-
}
|
|
777
|
-
if (cacheControl.sMaxAge) {
|
|
778
|
-
controls.push(`s-maxage=${cacheControl.sMaxAge}`);
|
|
779
|
-
}
|
|
780
|
-
if (cacheControl.noStore) {
|
|
781
|
-
controls.push("no-store");
|
|
782
|
-
}
|
|
783
|
-
if (cacheControl.noCache) {
|
|
784
|
-
controls.push("no-cache");
|
|
785
|
-
}
|
|
786
|
-
if (cacheControl.private) {
|
|
787
|
-
controls.push("private");
|
|
788
|
-
}
|
|
789
|
-
if (cacheControl.public) {
|
|
790
|
-
controls.push("public");
|
|
791
|
-
}
|
|
792
|
-
if (cacheControl.staleWhileRevalidate) {
|
|
793
|
-
controls.push(`stale-while-revalidate=${cacheControl.staleWhileRevalidate}`);
|
|
794
|
-
}
|
|
795
|
-
if (cacheControl.staleIfError) {
|
|
796
|
-
controls.push(`stale-if-error=${cacheControl.staleIfError}`);
|
|
797
|
-
}
|
|
798
|
-
return controls.join(", ");
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
const SAMESITE = {
|
|
802
|
-
lax: "Lax",
|
|
803
|
-
Lax: "Lax",
|
|
804
|
-
None: "None",
|
|
805
|
-
none: "None",
|
|
806
|
-
strict: "Strict",
|
|
807
|
-
Strict: "Strict"
|
|
808
|
-
};
|
|
809
|
-
const UNIT = {
|
|
810
|
-
seconds: 1,
|
|
811
|
-
minutes: 1 * 60,
|
|
812
|
-
hours: 1 * 60 * 60,
|
|
813
|
-
days: 1 * 60 * 60 * 24,
|
|
814
|
-
weeks: 1 * 60 * 60 * 24 * 7
|
|
815
|
-
};
|
|
816
|
-
function tryDecodeUriComponent(str) {
|
|
817
|
-
try {
|
|
818
|
-
return decodeURIComponent(str);
|
|
819
|
-
} catch {
|
|
820
|
-
return str;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
const parseCookieString = (cookieString) => {
|
|
824
|
-
const cookie = {};
|
|
825
|
-
if (typeof cookieString === "string" && cookieString !== "") {
|
|
826
|
-
const cookieSegments = cookieString.split(";");
|
|
827
|
-
for (const cookieSegment of cookieSegments) {
|
|
828
|
-
const separatorIndex = cookieSegment.indexOf("=");
|
|
829
|
-
if (separatorIndex !== -1) {
|
|
830
|
-
cookie[tryDecodeUriComponent(cookieSegment.slice(0, separatorIndex).trim())] = tryDecodeUriComponent(cookieSegment.slice(separatorIndex + 1).trim());
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
return cookie;
|
|
835
|
-
};
|
|
836
|
-
function resolveSameSite(sameSite) {
|
|
837
|
-
if (sameSite === true) {
|
|
838
|
-
return "Strict";
|
|
839
|
-
}
|
|
840
|
-
if (sameSite === false) {
|
|
841
|
-
return "None";
|
|
842
|
-
}
|
|
843
|
-
if (sameSite) {
|
|
844
|
-
return SAMESITE[sameSite];
|
|
845
|
-
}
|
|
846
|
-
return void 0;
|
|
847
|
-
}
|
|
848
|
-
const createSetCookieValue = (cookieName, cookieValue, options) => {
|
|
849
|
-
const c = [
|
|
850
|
-
`${cookieName}=${cookieValue}`
|
|
851
|
-
];
|
|
852
|
-
if (typeof options.domain === "string") {
|
|
853
|
-
c.push(`Domain=${options.domain}`);
|
|
854
|
-
}
|
|
855
|
-
if (typeof options.maxAge === "number") {
|
|
856
|
-
c.push(`Max-Age=${options.maxAge}`);
|
|
857
|
-
} else if (Array.isArray(options.maxAge)) {
|
|
858
|
-
c.push(`Max-Age=${options.maxAge[0] * UNIT[options.maxAge[1]]}`);
|
|
859
|
-
} else if (typeof options.expires === "number" || typeof options.expires == "string") {
|
|
860
|
-
c.push(`Expires=${options.expires}`);
|
|
861
|
-
} else if (options.expires instanceof Date) {
|
|
862
|
-
c.push(`Expires=${options.expires.toUTCString()}`);
|
|
863
|
-
}
|
|
864
|
-
if (options.httpOnly) {
|
|
865
|
-
c.push("HttpOnly");
|
|
866
|
-
}
|
|
867
|
-
if (typeof options.path === "string") {
|
|
868
|
-
c.push(`Path=${options.path}`);
|
|
869
|
-
}
|
|
870
|
-
const sameSite = resolveSameSite(options.sameSite);
|
|
871
|
-
if (sameSite) {
|
|
872
|
-
c.push(`SameSite=${sameSite}`);
|
|
873
|
-
}
|
|
874
|
-
if (options.secure) {
|
|
875
|
-
c.push("Secure");
|
|
876
|
-
}
|
|
877
|
-
return c.join("; ");
|
|
878
|
-
};
|
|
879
|
-
const REQ_COOKIE = /* @__PURE__ */ Symbol("request-cookies");
|
|
880
|
-
const RES_COOKIE = /* @__PURE__ */ Symbol("response-cookies");
|
|
881
|
-
const LIVE_COOKIE = /* @__PURE__ */ Symbol("live-cookies");
|
|
882
|
-
class Cookie {
|
|
883
|
-
[REQ_COOKIE];
|
|
884
|
-
[RES_COOKIE] = {};
|
|
885
|
-
[LIVE_COOKIE] = {};
|
|
886
|
-
appendCounter = 0;
|
|
887
|
-
constructor(cookieString) {
|
|
888
|
-
this[REQ_COOKIE] = parseCookieString(cookieString);
|
|
889
|
-
this[LIVE_COOKIE] = {
|
|
890
|
-
...this[REQ_COOKIE]
|
|
891
|
-
};
|
|
892
|
-
}
|
|
893
|
-
get(cookieName, live = true) {
|
|
894
|
-
const value = this[live ? LIVE_COOKIE : REQ_COOKIE][cookieName];
|
|
895
|
-
if (!value) {
|
|
896
|
-
return null;
|
|
897
|
-
}
|
|
898
|
-
return {
|
|
899
|
-
value,
|
|
900
|
-
json() {
|
|
901
|
-
return JSON.parse(value);
|
|
902
|
-
},
|
|
903
|
-
number() {
|
|
904
|
-
return Number(value);
|
|
905
|
-
}
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
getAll(live = true) {
|
|
909
|
-
return Object.keys(this[live ? LIVE_COOKIE : REQ_COOKIE]).reduce((cookies, cookieName) => {
|
|
910
|
-
cookies[cookieName] = this.get(cookieName);
|
|
911
|
-
return cookies;
|
|
912
|
-
}, {});
|
|
913
|
-
}
|
|
914
|
-
has(cookieName, live = true) {
|
|
915
|
-
return !!this[live ? LIVE_COOKIE : REQ_COOKIE][cookieName];
|
|
916
|
-
}
|
|
917
|
-
set(cookieName, cookieValue, options = {}) {
|
|
918
|
-
this[LIVE_COOKIE][cookieName] = typeof cookieValue === "string" ? cookieValue : JSON.stringify(cookieValue);
|
|
919
|
-
const resolvedValue = typeof cookieValue === "string" ? cookieValue : encodeURIComponent(JSON.stringify(cookieValue));
|
|
920
|
-
this[RES_COOKIE][cookieName] = createSetCookieValue(cookieName, resolvedValue, options);
|
|
921
|
-
}
|
|
922
|
-
append(cookieName, cookieValue, options = {}) {
|
|
923
|
-
this[LIVE_COOKIE][cookieName] = typeof cookieValue === "string" ? cookieValue : JSON.stringify(cookieValue);
|
|
924
|
-
const resolvedValue = typeof cookieValue === "string" ? cookieValue : encodeURIComponent(JSON.stringify(cookieValue));
|
|
925
|
-
this[RES_COOKIE][++this.appendCounter] = createSetCookieValue(cookieName, resolvedValue, options);
|
|
926
|
-
}
|
|
927
|
-
delete(name, options) {
|
|
928
|
-
this.set(name, "deleted", {
|
|
929
|
-
...options,
|
|
930
|
-
maxAge: 0
|
|
931
|
-
});
|
|
932
|
-
this[LIVE_COOKIE][name] = null;
|
|
933
|
-
}
|
|
934
|
-
headers() {
|
|
935
|
-
return Object.values(this[RES_COOKIE]);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
const mergeHeadersCookies = (headers, cookies) => {
|
|
939
|
-
const cookieHeaders = cookies.headers();
|
|
940
|
-
if (cookieHeaders.length > 0) {
|
|
941
|
-
const newHeaders = new Headers(headers);
|
|
942
|
-
for (const cookie of cookieHeaders) {
|
|
943
|
-
newHeaders.append("Set-Cookie", cookie);
|
|
944
|
-
}
|
|
945
|
-
return newHeaders;
|
|
946
|
-
}
|
|
947
|
-
return headers;
|
|
948
|
-
};
|
|
949
|
-
|
|
950
|
-
class RewriteMessage extends AbortMessage {
|
|
951
|
-
pathname;
|
|
952
|
-
constructor(pathname) {
|
|
953
|
-
super(), this.pathname = pathname;
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
const requestEventDeps = {
|
|
958
|
-
QDATA_KEY,
|
|
959
|
-
QACTION_KEY,
|
|
960
|
-
isPromise,
|
|
961
|
-
createCacheControl,
|
|
962
|
-
Cookie,
|
|
963
|
-
AbortMessage,
|
|
964
|
-
RedirectMessage,
|
|
965
|
-
RewriteMessage,
|
|
966
|
-
ServerError,
|
|
967
|
-
recognizeRequest,
|
|
968
|
-
trimRecognizedInternalPathname,
|
|
969
|
-
IsQLoader,
|
|
970
|
-
IsQAction,
|
|
971
|
-
QLoaderId,
|
|
972
|
-
QActionId,
|
|
973
|
-
encoder,
|
|
974
|
-
getContentType
|
|
975
|
-
};
|
|
976
|
-
function createRequestEvent(...args) {
|
|
977
|
-
return createRequestEventWithDeps(requestEventDeps, ...args);
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
async function runNextWithDeps(requestEv, rebuildRouteInfo, resolve, deps) {
|
|
981
|
-
try {
|
|
982
|
-
const isValidURL = (url) => new URL(url.pathname + url.search, url);
|
|
983
|
-
isValidURL(requestEv.originalUrl);
|
|
984
|
-
} catch {
|
|
985
|
-
const status = 404;
|
|
986
|
-
const message = "Resource Not Found";
|
|
987
|
-
requestEv.status(status);
|
|
988
|
-
requestEv.html(status, deps.getErrorHtml(status, message));
|
|
989
|
-
return new deps.ServerError(status, message);
|
|
990
|
-
}
|
|
991
|
-
let rewriteAttempt = 1;
|
|
992
|
-
async function runOnce() {
|
|
993
|
-
try {
|
|
994
|
-
await requestEv.next();
|
|
995
|
-
} catch (e) {
|
|
996
|
-
if (e instanceof deps.RedirectMessage) {
|
|
997
|
-
const stream = requestEv.getWritableStream();
|
|
998
|
-
await stream.close();
|
|
999
|
-
return e;
|
|
1000
|
-
} else if (e instanceof deps.RewriteMessage) {
|
|
1001
|
-
if (rewriteAttempt > 50) {
|
|
1002
|
-
return new Error(`Infinite rewrite loop`);
|
|
1003
|
-
}
|
|
1004
|
-
rewriteAttempt += 1;
|
|
1005
|
-
const url = new URL(requestEv.url);
|
|
1006
|
-
url.pathname = e.pathname;
|
|
1007
|
-
const { loadedRoute, requestHandlers } = await rebuildRouteInfo(url);
|
|
1008
|
-
requestEv.resetRoute(loadedRoute, requestHandlers, url);
|
|
1009
|
-
return await runOnce();
|
|
1010
|
-
} else if (e instanceof deps.AbortMessage) {
|
|
1011
|
-
return;
|
|
1012
|
-
} else if (e instanceof deps.ServerError && !requestEv.headersSent) {
|
|
1013
|
-
const status = e.status;
|
|
1014
|
-
const accept = requestEv.request.headers.get("Accept");
|
|
1015
|
-
if (accept && !accept.includes("text/html")) {
|
|
1016
|
-
requestEv.headers.set("Content-Type", "application/qwik-json");
|
|
1017
|
-
requestEv.send(status, await _serialize(e.data));
|
|
1018
|
-
} else {
|
|
1019
|
-
requestEv.html(status, deps.getErrorHtml(status, e.data));
|
|
1020
|
-
}
|
|
1021
|
-
return e;
|
|
1022
|
-
}
|
|
1023
|
-
if (!isDev$1) {
|
|
1024
|
-
try {
|
|
1025
|
-
if (!requestEv.headersSent) {
|
|
1026
|
-
requestEv.headers.set("content-type", "text/html; charset=utf-8");
|
|
1027
|
-
requestEv.cacheControl({
|
|
1028
|
-
noCache: true
|
|
1029
|
-
});
|
|
1030
|
-
requestEv.status(500);
|
|
1031
|
-
}
|
|
1032
|
-
const stream = requestEv.getWritableStream();
|
|
1033
|
-
if (!stream.locked) {
|
|
1034
|
-
const writer = stream.getWriter();
|
|
1035
|
-
await writer.write(deps.encoder.encode(deps.getErrorHtml(500, "Internal Server Error")));
|
|
1036
|
-
await writer.close();
|
|
1037
|
-
}
|
|
1038
|
-
} catch {
|
|
1039
|
-
console.error("Unable to render error page");
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
return e instanceof Error || typeof e === "object" && e !== null ? e : new Error(String(e));
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
try {
|
|
1046
|
-
return await runOnce();
|
|
1047
|
-
} finally {
|
|
1048
|
-
if (!requestEv.isDirty()) {
|
|
1049
|
-
resolve(null);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
function runQwikRouterWithDeps(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, basePathname, deps) {
|
|
1054
|
-
let resolve;
|
|
1055
|
-
const responsePromise = new Promise((r) => resolve = r);
|
|
1056
|
-
const requestEv = deps.createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, basePathname, resolve);
|
|
1057
|
-
return {
|
|
1058
|
-
response: responsePromise,
|
|
1059
|
-
requestEv,
|
|
1060
|
-
completion: deps.asyncRequestStore ? deps.asyncRequestStore.run(requestEv, runNextWithDeps, requestEv, rebuildRouteInfo, resolve, deps) : runNextWithDeps(requestEv, rebuildRouteInfo, resolve, deps)
|
|
1061
|
-
};
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, basePathname = "/") {
|
|
1065
|
-
return runQwikRouterWithDeps(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, basePathname, {
|
|
1066
|
-
AbortMessage,
|
|
1067
|
-
RedirectMessage,
|
|
1068
|
-
RewriteMessage,
|
|
1069
|
-
ServerError,
|
|
1070
|
-
asyncRequestStore: _asyncRequestStore,
|
|
1071
|
-
createRequestEvent,
|
|
1072
|
-
encoder,
|
|
1073
|
-
getErrorHtml
|
|
1074
|
-
});
|
|
1075
|
-
}
|
|
1
|
+
import { F as FULLPATH_HEADER, R as ROUTE_PATH_HEADER, l as loadRoute } from '../../chunks/head.qwik.mjs';
|
|
2
|
+
export { _ as _asyncRequestStore } from '../../chunks/head.qwik.mjs';
|
|
3
|
+
import { isDev } from '@qwik.dev/core';
|
|
4
|
+
import { d as devPreloadedRouteLoaders } from '../../chunks/dev-preloaded-route-loader.mjs';
|
|
5
|
+
import { r as recognizeRequest, t as trimRecognizedInternalPathname, I as IsQLoader, a as resolveValidInternalFullPathname, b as trimInternalPathname } from '../../chunks/request-path.mjs';
|
|
6
|
+
import { r as runQwikRouter, a as resolveRequestHandlers, b as renderQwikMiddleware } from '../../chunks/user-response.mjs';
|
|
7
|
+
export { R as RewriteMessage, c as clearLoaderCache, d as clearSsrCache, g as getErrorHtml, m as mergeHeadersCookies } from '../../chunks/user-response.mjs';
|
|
8
|
+
export { A as AbortMessage, R as RedirectMessage, S as ServerError } from '../../chunks/server-error.mjs';
|
|
1076
9
|
|
|
1077
10
|
let qwikRouterConfig;
|
|
1078
11
|
async function getConfig() {
|
|
12
|
+
if (isDev) {
|
|
13
|
+
return await import('@qwik-router-config');
|
|
14
|
+
}
|
|
1079
15
|
if (!qwikRouterConfig) {
|
|
1080
16
|
qwikRouterConfig = await import('@qwik-router-config');
|
|
1081
17
|
}
|
|
1082
18
|
return qwikRouterConfig;
|
|
1083
19
|
}
|
|
1084
|
-
function getRequestHandlerPathname(serverRequestEv) {
|
|
20
|
+
function getRequestHandlerPathname(serverRequestEv, isDevRequest = isDev) {
|
|
1085
21
|
const recognized = recognizeRequest(serverRequestEv.url.pathname);
|
|
1086
22
|
if (!recognized) {
|
|
1087
23
|
return serverRequestEv.url.pathname;
|
|
@@ -1090,11 +26,19 @@ function getRequestHandlerPathname(serverRequestEv) {
|
|
|
1090
26
|
if (recognized.type !== IsQLoader) {
|
|
1091
27
|
return loaderPathname;
|
|
1092
28
|
}
|
|
1093
|
-
|
|
29
|
+
const routePath = serverRequestEv.request.headers.get(FULLPATH_HEADER) ?? (isDevRequest ? serverRequestEv.request.headers.get(ROUTE_PATH_HEADER) : null);
|
|
30
|
+
return resolveValidInternalFullPathname(loaderPathname, routePath) ?? loaderPathname;
|
|
1094
31
|
}
|
|
1095
|
-
async function loadRequestHandlers(qwikRouterConfig2, pathname, method, checkOrigin, renderFn) {
|
|
32
|
+
async function loadRequestHandlers(qwikRouterConfig2, pathname, method, checkOrigin, renderFn, serverRequestEv) {
|
|
1096
33
|
const { routes, serverPlugins, cacheModules } = qwikRouterConfig2;
|
|
1097
34
|
const loadedRoute = await loadRoute(routes, cacheModules, pathname);
|
|
35
|
+
const loader = isDev ? devPreloadedRouteLoaders.get(serverRequestEv.request) : void 0;
|
|
36
|
+
const lastModule = loadedRoute.$mods$[loadedRoute.$mods$.length - 1];
|
|
37
|
+
if (loader && lastModule) {
|
|
38
|
+
loadedRoute.$mods$[loadedRoute.$mods$.length - 1] = Object.assign({}, lastModule, {
|
|
39
|
+
__preloadedRouteLoader: loader
|
|
40
|
+
});
|
|
41
|
+
}
|
|
1098
42
|
const requestHandlers = resolveRequestHandlers(serverPlugins, loadedRoute, method, checkOrigin, renderQwikMiddleware(renderFn));
|
|
1099
43
|
return {
|
|
1100
44
|
loadedRoute,
|
|
@@ -1108,30 +52,17 @@ async function requestHandler(serverRequestEv, opts) {
|
|
|
1108
52
|
if (pathname === "/.well-known" || pathname.startsWith("/.well-known/")) {
|
|
1109
53
|
return null;
|
|
1110
54
|
}
|
|
1111
|
-
const { loadedRoute, requestHandlers } = await loadRequestHandlers(config, pathname, serverRequestEv.request.method, checkOrigin ?? true, render);
|
|
55
|
+
const { loadedRoute, requestHandlers } = await loadRequestHandlers(config, pathname, serverRequestEv.request.method, checkOrigin ?? true, render, serverRequestEv);
|
|
1112
56
|
if (config.fallthrough && loadedRoute.$notFound$) {
|
|
1113
57
|
return null;
|
|
1114
58
|
}
|
|
1115
59
|
const rebuildRouteInfo = async (url) => {
|
|
1116
60
|
const cleanPathname = trimInternalPathname(url.pathname);
|
|
1117
|
-
return loadRequestHandlers(config, cleanPathname, serverRequestEv.request.method, checkOrigin ?? true, render);
|
|
61
|
+
return loadRequestHandlers(config, cleanPathname, serverRequestEv.request.method, checkOrigin ?? true, render, serverRequestEv);
|
|
1118
62
|
};
|
|
1119
63
|
return runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, config.basePathname);
|
|
1120
64
|
}
|
|
1121
65
|
|
|
1122
|
-
const notFounds = [
|
|
1123
|
-
// Will be replaced in post-build with the 404s generated by SSG
|
|
1124
|
-
"__QWIK_ROUTER_NOT_FOUND_ARRAY__"
|
|
1125
|
-
];
|
|
1126
|
-
function getNotFound(prefix) {
|
|
1127
|
-
for (const [path, html] of notFounds) {
|
|
1128
|
-
if (prefix.startsWith(path)) {
|
|
1129
|
-
return html;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
return minimalHtmlResponse(404, "Resource Not Found");
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
66
|
const staticPaths = /* @__PURE__ */ new Set([
|
|
1136
67
|
"__QWIK_ROUTER_STATIC_PATHS_ARRAY__"
|
|
1137
68
|
]);
|
|
@@ -1146,17 +77,7 @@ function isStaticPath(method, url) {
|
|
|
1146
77
|
if (p.startsWith("/" + (globalThis.__QWIK_ASSETS_DIR__ || "assets") + "/")) {
|
|
1147
78
|
return true;
|
|
1148
79
|
}
|
|
1149
|
-
|
|
1150
|
-
return true;
|
|
1151
|
-
}
|
|
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)) {
|
|
1156
|
-
return true;
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
return false;
|
|
80
|
+
return staticPaths.has(p);
|
|
1160
81
|
}
|
|
1161
82
|
|
|
1162
83
|
class _TextEncoderStream_polyfill {
|
|
@@ -1216,4 +137,4 @@ class _TextEncoderStream_polyfill {
|
|
|
1216
137
|
}
|
|
1217
138
|
}
|
|
1218
139
|
|
|
1219
|
-
export {
|
|
140
|
+
export { _TextEncoderStream_polyfill, isStaticPath, requestHandler };
|