@qwik.dev/router 2.0.0-beta.18 → 2.0.0-beta.19
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/index.d.ts +57 -6
- package/lib/index.qwik.mjs +32 -9
- package/lib/middleware/bun/index.d.ts +11 -0
- package/lib/middleware/bun/index.mjs +11 -3
- package/lib/middleware/deno/index.d.ts +11 -0
- package/lib/middleware/deno/index.mjs +11 -3
- package/lib/middleware/request-handler/index.d.ts +5 -5
- package/lib/middleware/request-handler/index.mjs +56 -17
- package/package.json +3 -3
package/lib/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ import type { ResolveSyncValue } from '@qwik.dev/router/middleware/request-handl
|
|
|
25
25
|
import type { SerializationStrategy } from '@qwik.dev/core/internal';
|
|
26
26
|
import type * as v from 'valibot';
|
|
27
27
|
import type { ValueOrPromise } from '@qwik.dev/core';
|
|
28
|
+
import { ValueOrPromise as ValueOrPromise_2 } from '@qwik.dev/core/internal';
|
|
28
29
|
import { z } from 'zod';
|
|
29
30
|
import type * as z_2 from 'zod';
|
|
30
31
|
|
|
@@ -593,12 +594,6 @@ export declare const QWIK_CITY_SCROLLER = "_qCityScroller";
|
|
|
593
594
|
/** @public */
|
|
594
595
|
export declare const QWIK_ROUTER_SCROLLER = "_qRouterScroller";
|
|
595
596
|
|
|
596
|
-
/**
|
|
597
|
-
* @deprecated Use `QwikRouterMockProps` instead. will be removed in V3
|
|
598
|
-
* @public
|
|
599
|
-
*/
|
|
600
|
-
export declare type QwikCityMockProps = QwikRouterMockProps;
|
|
601
|
-
|
|
602
597
|
/**
|
|
603
598
|
* @deprecated Use `useQwikMockRouter()` instead. Will be removed in V3
|
|
604
599
|
* @public
|
|
@@ -642,11 +637,62 @@ export declare interface QwikRouterEnvData {
|
|
|
642
637
|
loadedRoute: LoadedRoute | null;
|
|
643
638
|
}
|
|
644
639
|
|
|
640
|
+
/** @public */
|
|
641
|
+
export declare interface QwikRouterMockActionProp<T = any> {
|
|
642
|
+
/** The action function to mock. */
|
|
643
|
+
action: Action<T>;
|
|
644
|
+
/** The QRL function that will be called when the action is submitted. */
|
|
645
|
+
handler: QRL<(data: T) => ValueOrPromise_2<RouteActionResolver>>;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/** @public */
|
|
649
|
+
export declare interface QwikRouterMockLoaderProp<T = any> {
|
|
650
|
+
/** The loader function to mock. */
|
|
651
|
+
loader: Loader_2<T>;
|
|
652
|
+
/** The data to return when the loader is called. */
|
|
653
|
+
data: T;
|
|
654
|
+
}
|
|
655
|
+
|
|
645
656
|
/** @public */
|
|
646
657
|
export declare interface QwikRouterMockProps {
|
|
658
|
+
/**
|
|
659
|
+
* Allow mocking the url returned by `useLocation` hook.
|
|
660
|
+
*
|
|
661
|
+
* Default: `http://localhost/`
|
|
662
|
+
*/
|
|
647
663
|
url?: string;
|
|
664
|
+
/** Allow mocking the route params returned by `useLocation` hook. */
|
|
648
665
|
params?: Record<string, string>;
|
|
666
|
+
/** Allow mocking the `goto` function returned by `useNavigate` hook. */
|
|
649
667
|
goto?: RouteNavigate;
|
|
668
|
+
/**
|
|
669
|
+
* Allow mocking data for loaders defined with `routeLoader$` function.
|
|
670
|
+
*
|
|
671
|
+
* ```
|
|
672
|
+
* [
|
|
673
|
+
* {
|
|
674
|
+
* loader: useProductData,
|
|
675
|
+
* data: { product: { name: 'Test Product' } },
|
|
676
|
+
* },
|
|
677
|
+
* ];
|
|
678
|
+
* ```
|
|
679
|
+
*/
|
|
680
|
+
loaders?: Array<QwikRouterMockLoaderProp<any>>;
|
|
681
|
+
/**
|
|
682
|
+
* Allow mocking actions defined with `routeAction$` function.
|
|
683
|
+
*
|
|
684
|
+
* ```
|
|
685
|
+
* [
|
|
686
|
+
* {
|
|
687
|
+
* action: useAddUser,
|
|
688
|
+
* handler: $(async (data) => {
|
|
689
|
+
* console.log('useAddUser action called with data:', data);
|
|
690
|
+
* }),
|
|
691
|
+
* },
|
|
692
|
+
* ];
|
|
693
|
+
* ```
|
|
694
|
+
*/
|
|
695
|
+
actions?: Array<QwikRouterMockActionProp<any>>;
|
|
650
696
|
}
|
|
651
697
|
|
|
652
698
|
/** @public */
|
|
@@ -706,6 +752,11 @@ export declare const routeAction$: ActionConstructor;
|
|
|
706
752
|
|
|
707
753
|
/* Excluded from this release type: routeActionQrl */
|
|
708
754
|
|
|
755
|
+
declare type RouteActionResolver = {
|
|
756
|
+
status: number;
|
|
757
|
+
result: unknown;
|
|
758
|
+
};
|
|
759
|
+
|
|
709
760
|
/** @public */
|
|
710
761
|
export declare type RouteData = [
|
|
711
762
|
routeName: string,
|
package/lib/index.qwik.mjs
CHANGED
|
@@ -65,14 +65,10 @@ const Link = component$((props) => {
|
|
|
65
65
|
scroll,
|
|
66
66
|
...linkProps
|
|
67
67
|
} = /* @__PURE__ */ (() => props)();
|
|
68
|
-
const clientNavPath = untrack(
|
|
68
|
+
const clientNavPath = untrack(getClientNavPath, { ...linkProps, reload }, loc);
|
|
69
69
|
linkProps.href = clientNavPath || originalHref;
|
|
70
|
-
const prefetchData =
|
|
71
|
-
|
|
72
|
-
);
|
|
73
|
-
const prefetch = untrack(
|
|
74
|
-
() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPreload(clientNavPath, loc)
|
|
75
|
-
);
|
|
70
|
+
const prefetchData = !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" || void 0;
|
|
71
|
+
const prefetch = prefetchData || !!clientNavPath && prefetchProp !== false && untrack(shouldPreload, clientNavPath, loc);
|
|
76
72
|
const handlePrefetch = prefetch ? $((_, elm) => {
|
|
77
73
|
if (navigator.connection?.saveData) {
|
|
78
74
|
return;
|
|
@@ -550,7 +546,9 @@ const useQwikRouter = (props) => {
|
|
|
550
546
|
} = typeof opt === "object" ? opt : { forceReload: opt };
|
|
551
547
|
internalState.navCount++;
|
|
552
548
|
if (isBrowser && type === "link" && routeInternal.value.type === "initial") {
|
|
553
|
-
|
|
549
|
+
const url2 = new URL(window.location.href);
|
|
550
|
+
routeInternal.value.dest = url2;
|
|
551
|
+
routeLocation.url = url2;
|
|
554
552
|
}
|
|
555
553
|
const lastDest = routeInternal.value.dest;
|
|
556
554
|
const dest = path === void 0 ? lastDest : typeof path === "number" ? path : toUrl(path, routeLocation.url);
|
|
@@ -952,7 +950,14 @@ const useQwikMockRouter = (props) => {
|
|
|
952
950
|
},
|
|
953
951
|
{ deep: false }
|
|
954
952
|
);
|
|
955
|
-
const
|
|
953
|
+
const loadersData = props.loaders?.reduce(
|
|
954
|
+
(acc, { loader, data }) => {
|
|
955
|
+
acc[loader.__id] = data;
|
|
956
|
+
return acc;
|
|
957
|
+
},
|
|
958
|
+
{}
|
|
959
|
+
);
|
|
960
|
+
const loaderState = useStore(loadersData ?? {}, { deep: false });
|
|
956
961
|
const goto = props.goto ?? $(async () => {
|
|
957
962
|
console.warn("QwikRouterMockProvider: goto not provided");
|
|
958
963
|
});
|
|
@@ -973,6 +978,24 @@ const useQwikMockRouter = (props) => {
|
|
|
973
978
|
useContextProvider(RouteNavigateContext, goto);
|
|
974
979
|
useContextProvider(RouteStateContext, loaderState);
|
|
975
980
|
useContextProvider(RouteActionContext, actionState);
|
|
981
|
+
const actionsMocks = props.actions?.reduce(
|
|
982
|
+
(acc, { action, handler }) => {
|
|
983
|
+
acc[action.__id] = handler;
|
|
984
|
+
return acc;
|
|
985
|
+
},
|
|
986
|
+
{}
|
|
987
|
+
);
|
|
988
|
+
useTask$(async ({ track }) => {
|
|
989
|
+
const action = track(actionState);
|
|
990
|
+
if (!action?.resolve) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
const mock = actionsMocks?.[action.id];
|
|
994
|
+
if (mock) {
|
|
995
|
+
const actionResult = await mock(action.data);
|
|
996
|
+
action.resolve(actionResult);
|
|
997
|
+
}
|
|
998
|
+
});
|
|
976
999
|
};
|
|
977
1000
|
const QwikRouterMockProvider = component$((props) => {
|
|
978
1001
|
useQwikMockRouter(props);
|
|
@@ -29,6 +29,17 @@ export declare interface QwikRouterBunOptions extends ServerRenderOptions {
|
|
|
29
29
|
/** Set the Cache-Control header for all static files */
|
|
30
30
|
cacheControl?: string;
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Provide a function that computes the origin of the server, used to resolve relative URLs and
|
|
34
|
+
* validate the request origin against CSRF attacks.
|
|
35
|
+
*
|
|
36
|
+
* When not specified, it defaults to the `ORIGIN` environment variable (if set).
|
|
37
|
+
*
|
|
38
|
+
* If `ORIGIN` is not set, it's derived from the incoming request, which is not recommended for
|
|
39
|
+
* production use.
|
|
40
|
+
*/
|
|
41
|
+
getOrigin?: (request: Request) => string | null;
|
|
42
|
+
/** Provide a function that returns a `ClientConn` for the given request. */
|
|
32
43
|
getClientConn?: (request: Request) => ClientConn;
|
|
33
44
|
}
|
|
34
45
|
|
|
@@ -3,6 +3,14 @@ import { _TextEncoderStream_polyfill, isStaticPath, getNotFound, mergeHeadersCoo
|
|
|
3
3
|
import { join, extname } from 'node:path';
|
|
4
4
|
import { M as MIME_TYPES } from '../../chunks/mime-types.mjs';
|
|
5
5
|
|
|
6
|
+
function getRequestUrl(request, opts) {
|
|
7
|
+
const url = new URL(request.url);
|
|
8
|
+
const origin = opts.getOrigin?.(request) ?? Bun.env.ORIGIN;
|
|
9
|
+
if (!origin) {
|
|
10
|
+
return url;
|
|
11
|
+
}
|
|
12
|
+
return new URL(`${url.pathname}${url.search}${url.hash}`, origin);
|
|
13
|
+
}
|
|
6
14
|
function createQwikRouter(opts) {
|
|
7
15
|
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
|
|
8
16
|
console.warn("qwikCityPlan is deprecated. Simply remove it.");
|
|
@@ -15,7 +23,7 @@ function createQwikRouter(opts) {
|
|
|
15
23
|
const staticFolder = opts.static?.root ?? join(Bun.fileURLToPath(import.meta.url), "..", "..", "dist");
|
|
16
24
|
async function router(request) {
|
|
17
25
|
try {
|
|
18
|
-
const url =
|
|
26
|
+
const url = getRequestUrl(request, opts);
|
|
19
27
|
const serverRequestEv = {
|
|
20
28
|
mode: "server",
|
|
21
29
|
locale: void 0,
|
|
@@ -71,7 +79,7 @@ function createQwikRouter(opts) {
|
|
|
71
79
|
}
|
|
72
80
|
const notFound = async (request) => {
|
|
73
81
|
try {
|
|
74
|
-
const url =
|
|
82
|
+
const url = getRequestUrl(request, opts);
|
|
75
83
|
const notFoundHtml = !request.headers.get("accept")?.includes("text/html") || isStaticPath(request.method || "GET", url) ? "Not Found" : getNotFound(url.pathname);
|
|
76
84
|
return new Response(notFoundHtml, {
|
|
77
85
|
status: 404,
|
|
@@ -103,7 +111,7 @@ function createQwikRouter(opts) {
|
|
|
103
111
|
};
|
|
104
112
|
const staticFile = async (request) => {
|
|
105
113
|
try {
|
|
106
|
-
const url =
|
|
114
|
+
const url = getRequestUrl(request, opts);
|
|
107
115
|
if (isStaticPath(request.method || "GET", url)) {
|
|
108
116
|
const { filePath, content } = await openStaticFile(url);
|
|
109
117
|
if (!await content.exists()) {
|
|
@@ -36,6 +36,17 @@ export declare interface QwikRouterDenoOptions extends ServerRenderOptions {
|
|
|
36
36
|
/** Set the Cache-Control header for all static files */
|
|
37
37
|
cacheControl?: string;
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Provide a function that computes the origin of the server, used to resolve relative URLs and
|
|
41
|
+
* validate the request origin against CSRF attacks.
|
|
42
|
+
*
|
|
43
|
+
* When not specified, it defaults to the `ORIGIN` environment variable (if set).
|
|
44
|
+
*
|
|
45
|
+
* If `ORIGIN` is not set, it's derived from the incoming request, which is not recommended for
|
|
46
|
+
* production use.
|
|
47
|
+
*/
|
|
48
|
+
getOrigin?: (request: Request, info?: ServeHandlerInfo) => string | null;
|
|
49
|
+
/** Provide a function that returns a `ClientConn` for the given request. */
|
|
39
50
|
getClientConn?: (request: Request, info: ServeHandlerInfo) => ClientConn;
|
|
40
51
|
}
|
|
41
52
|
|
|
@@ -3,6 +3,14 @@ import { isStaticPath, getNotFound, mergeHeadersCookies, requestHandler } from '
|
|
|
3
3
|
import { M as MIME_TYPES } from '../../chunks/mime-types.mjs';
|
|
4
4
|
import { join, fromFileUrl, extname } from 'https://deno.land/std/path/mod.ts';
|
|
5
5
|
|
|
6
|
+
function getRequestUrl(request, opts, info) {
|
|
7
|
+
const url = new URL(request.url);
|
|
8
|
+
const origin = opts.getOrigin?.(request, info) ?? Deno.env?.get?.("ORIGIN");
|
|
9
|
+
if (!origin) {
|
|
10
|
+
return url;
|
|
11
|
+
}
|
|
12
|
+
return new URL(`${url.pathname}${url.search}${url.hash}`, origin);
|
|
13
|
+
}
|
|
6
14
|
function createQwikRouter(opts) {
|
|
7
15
|
if (opts.qwikCityPlan && !opts.qwikRouterConfig) {
|
|
8
16
|
console.warn("qwikCityPlan is deprecated. Simply remove it.");
|
|
@@ -14,7 +22,7 @@ function createQwikRouter(opts) {
|
|
|
14
22
|
const staticFolder = opts.static?.root ?? join(fromFileUrl(import.meta.url), "..", "..", "dist");
|
|
15
23
|
async function router(request, info) {
|
|
16
24
|
try {
|
|
17
|
-
const url =
|
|
25
|
+
const url = getRequestUrl(request, opts, info);
|
|
18
26
|
const serverRequestEv = {
|
|
19
27
|
mode: "server",
|
|
20
28
|
locale: void 0,
|
|
@@ -63,7 +71,7 @@ function createQwikRouter(opts) {
|
|
|
63
71
|
}
|
|
64
72
|
const notFound = async (request) => {
|
|
65
73
|
try {
|
|
66
|
-
const url =
|
|
74
|
+
const url = getRequestUrl(request, opts);
|
|
67
75
|
const notFoundHtml = !request.headers.get("accept")?.includes("text/html") || isStaticPath(request.method || "GET", url) ? "Not Found" : getNotFound(url.pathname);
|
|
68
76
|
return new Response(notFoundHtml, {
|
|
69
77
|
status: 404,
|
|
@@ -96,7 +104,7 @@ function createQwikRouter(opts) {
|
|
|
96
104
|
};
|
|
97
105
|
const staticFile = async (request) => {
|
|
98
106
|
try {
|
|
99
|
-
const url =
|
|
107
|
+
const url = getRequestUrl(request, opts);
|
|
100
108
|
if (isStaticPath(request.method || "GET", url)) {
|
|
101
109
|
const { filePath, content } = await openStaticFile(url);
|
|
102
110
|
const ext = extname(filePath).replace(/^\./, "");
|
|
@@ -546,11 +546,11 @@ export declare interface RequestEventCommon<PLATFORM = QwikRouterPlatform> exten
|
|
|
546
546
|
readonly exit: () => AbortMessage;
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
-
declare interface RequestEventInternal extends RequestEvent
|
|
550
|
-
[RequestEvLoaders]: Record<string, ValueOrPromise<unknown> | undefined>;
|
|
551
|
-
[RequestEvLoaderSerializationStrategyMap]: Map<string, SerializationStrategy>;
|
|
552
|
-
[RequestEvMode]: ServerRequestMode;
|
|
553
|
-
[RequestEvRoute]: LoadedRoute | null;
|
|
549
|
+
declare interface RequestEventInternal extends Readonly<RequestEvent>, Readonly<RequestEventLoader> {
|
|
550
|
+
readonly [RequestEvLoaders]: Record<string, ValueOrPromise<unknown> | undefined>;
|
|
551
|
+
readonly [RequestEvLoaderSerializationStrategyMap]: Map<string, SerializationStrategy>;
|
|
552
|
+
readonly [RequestEvMode]: ServerRequestMode;
|
|
553
|
+
readonly [RequestEvRoute]: LoadedRoute | null;
|
|
554
554
|
/**
|
|
555
555
|
* Check if this request is already written to.
|
|
556
556
|
*
|
|
@@ -557,8 +557,12 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
|
|
|
557
557
|
check();
|
|
558
558
|
status = statusCode;
|
|
559
559
|
if (url2) {
|
|
560
|
-
if (
|
|
561
|
-
|
|
560
|
+
if (
|
|
561
|
+
// //test.com
|
|
562
|
+
/^\/\//.test(url2) || // /test//path
|
|
563
|
+
/([^:])\/\/+/.test(url2)
|
|
564
|
+
) {
|
|
565
|
+
const fixedURL = url2.replace(/^\/\/+/, "/").replace(/([^:])\/\/+/g, "$1/");
|
|
562
566
|
console.warn(`Redirect URL ${url2} is invalid, fixing to ${fixedURL}`);
|
|
563
567
|
url2 = fixedURL;
|
|
564
568
|
}
|
|
@@ -634,7 +638,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, baseP
|
|
|
634
638
|
return writableStream;
|
|
635
639
|
}
|
|
636
640
|
};
|
|
637
|
-
return
|
|
641
|
+
return requestEv;
|
|
638
642
|
}
|
|
639
643
|
function getRequestLoaders(requestEv) {
|
|
640
644
|
return requestEv[RequestEvLoaders];
|
|
@@ -650,7 +654,7 @@ function getRequestMode(requestEv) {
|
|
|
650
654
|
}
|
|
651
655
|
const ABORT_INDEX = Number.MAX_SAFE_INTEGER;
|
|
652
656
|
const parseRequest = async ({ request, method, query }, sharedMap) => {
|
|
653
|
-
const type = request.headers
|
|
657
|
+
const type = getContentType(request.headers);
|
|
654
658
|
if (type === "application/x-www-form-urlencoded" || type === "multipart/form-data") {
|
|
655
659
|
const formData = await request.formData();
|
|
656
660
|
sharedMap.set(RequestEvSharedActionFormData, formData);
|
|
@@ -672,21 +676,40 @@ const parseRequest = async ({ request, method, query }, sharedMap) => {
|
|
|
672
676
|
}
|
|
673
677
|
return void 0;
|
|
674
678
|
};
|
|
679
|
+
const isDangerousKey = (k) => k === "__proto__" || k === "constructor" || k === "prototype";
|
|
675
680
|
const formToObj = (formData) => {
|
|
676
|
-
const values =
|
|
677
|
-
|
|
681
|
+
const values = /* @__PURE__ */ Object.create(null);
|
|
682
|
+
for (const [name, value] of formData) {
|
|
683
|
+
const keys = name.split(".");
|
|
684
|
+
let hasDangerousKey = false;
|
|
685
|
+
for (let i = 0; i < keys.length; i++) {
|
|
686
|
+
if (isDangerousKey(keys[i])) {
|
|
687
|
+
hasDangerousKey = true;
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
if (hasDangerousKey) {
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
let object = values;
|
|
695
|
+
for (let i = 0; i < keys.length; i++) {
|
|
696
|
+
const key = keys[i];
|
|
678
697
|
if (key.endsWith("[]")) {
|
|
679
698
|
const arrayKey = key.slice(0, -2);
|
|
699
|
+
if (isDangerousKey(arrayKey)) {
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
680
702
|
object[arrayKey] = object[arrayKey] || [];
|
|
681
|
-
|
|
703
|
+
object[arrayKey].push(value);
|
|
704
|
+
break;
|
|
682
705
|
}
|
|
683
|
-
if (
|
|
684
|
-
|
|
706
|
+
if (i < keys.length - 1) {
|
|
707
|
+
object = object[key] = object[key] || (Number.isNaN(+keys[i + 1]) ? /* @__PURE__ */ Object.create(null) : []);
|
|
708
|
+
} else {
|
|
709
|
+
object[key] = value;
|
|
685
710
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
return values2;
|
|
689
|
-
}, {});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
690
713
|
return values;
|
|
691
714
|
};
|
|
692
715
|
|
|
@@ -1035,6 +1058,13 @@ function fixTrailingSlash(ev) {
|
|
|
1035
1058
|
const { basePathname, originalUrl, sharedMap } = ev;
|
|
1036
1059
|
const { pathname, search } = originalUrl;
|
|
1037
1060
|
const isQData = sharedMap.has(IsQData);
|
|
1061
|
+
if (
|
|
1062
|
+
// all valid pathnames must start with a single slash
|
|
1063
|
+
!pathname.startsWith("/") || // protocol-relative URLs are not allowed like: //test.com, ///bad.com
|
|
1064
|
+
pathname.startsWith("//")
|
|
1065
|
+
) {
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1038
1068
|
if (!isQData && pathname !== basePathname && !pathname.endsWith(".html")) {
|
|
1039
1069
|
if (!globalThis.__NO_TRAILING_SLASH__) {
|
|
1040
1070
|
if (!pathname.endsWith("/")) {
|
|
@@ -1089,13 +1119,14 @@ function csrfCheckMiddleware(requestEv) {
|
|
|
1089
1119
|
checkCSRF(requestEv);
|
|
1090
1120
|
}
|
|
1091
1121
|
function checkCSRF(requestEv, laxProto) {
|
|
1092
|
-
const
|
|
1122
|
+
const contentType = requestEv.request.headers.get("content-type");
|
|
1123
|
+
const isSimpleRequest = !contentType || isContentType(
|
|
1093
1124
|
requestEv.request.headers,
|
|
1094
1125
|
"application/x-www-form-urlencoded",
|
|
1095
1126
|
"multipart/form-data",
|
|
1096
1127
|
"text/plain"
|
|
1097
1128
|
);
|
|
1098
|
-
if (
|
|
1129
|
+
if (isSimpleRequest) {
|
|
1099
1130
|
const inputOrigin = requestEv.request.headers.get("origin");
|
|
1100
1131
|
const origin = requestEv.url.origin;
|
|
1101
1132
|
let forbidden = inputOrigin !== origin;
|
|
@@ -1253,9 +1284,17 @@ async function measure(requestEv, name, fn) {
|
|
|
1253
1284
|
measurements.push([name, duration]);
|
|
1254
1285
|
}
|
|
1255
1286
|
}
|
|
1287
|
+
function getContentType(headers) {
|
|
1288
|
+
return (headers.get("content-type")?.split(/[;,]/, 1)[0].trim() ?? "").toLowerCase();
|
|
1289
|
+
}
|
|
1256
1290
|
function isContentType(headers, ...types) {
|
|
1257
|
-
const type = headers
|
|
1258
|
-
|
|
1291
|
+
const type = getContentType(headers);
|
|
1292
|
+
for (let i = 0; i < types.length; i++) {
|
|
1293
|
+
if (types[i].toLowerCase() === type) {
|
|
1294
|
+
return true;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return false;
|
|
1259
1298
|
}
|
|
1260
1299
|
|
|
1261
1300
|
let _asyncRequestStore;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwik.dev/router",
|
|
3
3
|
"description": "The router for Qwik.",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.19",
|
|
5
5
|
"bugs": "https://github.com/QwikDev/qwik/issues",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@azure/functions": "3.5.1",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"tsm": "2.3.0",
|
|
41
41
|
"typescript": "5.9.3",
|
|
42
42
|
"uvu": "0.5.6",
|
|
43
|
-
"@qwik.dev/core": "2.0.0-beta.
|
|
43
|
+
"@qwik.dev/core": "2.0.0-beta.19"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"main": "./lib/index.qwik.mjs",
|
|
170
170
|
"peerDependencies": {
|
|
171
171
|
"vite": ">=5 <8",
|
|
172
|
-
"@qwik.dev/core": "^2.0.0-beta.
|
|
172
|
+
"@qwik.dev/core": "^2.0.0-beta.19"
|
|
173
173
|
},
|
|
174
174
|
"publishConfig": {
|
|
175
175
|
"access": "public"
|