react-router 7.11.0-pre.0 → 7.12.0-pre.0
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/CHANGELOG.md +52 -2
- package/dist/development/{browser-Cv4JZyZ5.d.mts → browser-BEPxnEBW.d.mts} +4 -2
- package/dist/{production/browser-Cv4JZyZ5.d.mts → development/browser-CJ9_du-U.d.ts} +4 -2
- package/dist/development/{chunk-QMKP6CC3.mjs → chunk-2RQJSHF5.mjs} +111 -11
- package/dist/development/{chunk-JKMHOZYW.js → chunk-AUGQXA25.js} +98 -108
- package/dist/development/{chunk-OVG6YSZ5.js → chunk-JBLDGBX7.js} +7 -7
- package/dist/development/{chunk-KRMLYMWA.mjs → chunk-KYKH2NCS.mjs} +122 -50
- package/dist/development/{chunk-UO7KGW2U.js → chunk-MNTWZBMV.js} +117 -35
- package/dist/development/dom-export.d.mts +2 -2
- package/dist/development/dom-export.d.ts +2 -2
- package/dist/development/dom-export.js +35 -30
- package/dist/development/dom-export.mjs +12 -7
- package/dist/development/{index-react-server-client-P7VgYu6T.d.mts → index-react-server-client-IoJGLOqV.d.mts} +3 -1
- package/dist/{production/index-react-server-client-Cv5Q9lf0.d.ts → development/index-react-server-client-gGyf-7Xp.d.ts} +3 -1
- package/dist/development/index-react-server-client.d.mts +2 -2
- package/dist/development/index-react-server-client.d.ts +2 -2
- package/dist/development/index-react-server-client.js +4 -4
- package/dist/development/index-react-server-client.mjs +2 -2
- package/dist/development/index-react-server.d.mts +3 -1
- package/dist/development/index-react-server.d.ts +3 -1
- package/dist/development/index-react-server.js +92 -7
- package/dist/development/index-react-server.mjs +92 -7
- package/dist/development/index.d.mts +9 -9
- package/dist/development/index.d.ts +9 -9
- package/dist/development/index.js +205 -101
- package/dist/development/index.mjs +7 -3
- package/dist/{production/instrumentation-BlrVzjbg.d.ts → development/instrumentation-DvHY1sgY.d.ts} +45 -1
- package/dist/development/lib/types/internal.d.mts +2 -2
- package/dist/development/lib/types/internal.d.ts +2 -2
- package/dist/development/lib/types/internal.js +1 -1
- package/dist/development/lib/types/internal.mjs +1 -1
- package/dist/development/{register-BGQUMCK4.d.ts → register-Bm80E9qL.d.ts} +1 -1
- package/dist/development/{register-DTJJbt1o.d.mts → register-CS_tiXsm.d.mts} +1 -1
- package/dist/development/{router-5fbeEIMQ.d.mts → router-5iOvts3c.d.mts} +45 -1
- package/dist/{development/browser-o-qhcuhA.d.ts → production/browser-BEPxnEBW.d.mts} +4 -2
- package/dist/production/{browser-o-qhcuhA.d.ts → browser-CJ9_du-U.d.ts} +4 -2
- package/dist/production/{chunk-IDHO4Q57.mjs → chunk-HFQUWXEK.mjs} +122 -50
- package/dist/production/{chunk-J4JITZ76.mjs → chunk-ILRYJQTC.mjs} +111 -11
- package/dist/production/{chunk-YGB3JEIP.js → chunk-O6YLM5NB.js} +7 -7
- package/dist/production/{chunk-M5W3Q3T5.js → chunk-QWJQISZK.js} +98 -108
- package/dist/production/{chunk-AO22ZXHI.js → chunk-ZR2NIBH2.js} +117 -35
- package/dist/production/dom-export.d.mts +2 -2
- package/dist/production/dom-export.d.ts +2 -2
- package/dist/production/dom-export.js +35 -30
- package/dist/production/dom-export.mjs +12 -7
- package/dist/production/{index-react-server-client-P7VgYu6T.d.mts → index-react-server-client-IoJGLOqV.d.mts} +3 -1
- package/dist/{development/index-react-server-client-Cv5Q9lf0.d.ts → production/index-react-server-client-gGyf-7Xp.d.ts} +3 -1
- package/dist/production/index-react-server-client.d.mts +2 -2
- package/dist/production/index-react-server-client.d.ts +2 -2
- package/dist/production/index-react-server-client.js +4 -4
- package/dist/production/index-react-server-client.mjs +2 -2
- package/dist/production/index-react-server.d.mts +3 -1
- package/dist/production/index-react-server.d.ts +3 -1
- package/dist/production/index-react-server.js +92 -7
- package/dist/production/index-react-server.mjs +92 -7
- package/dist/production/index.d.mts +9 -9
- package/dist/production/index.d.ts +9 -9
- package/dist/production/index.js +205 -101
- package/dist/production/index.mjs +7 -3
- package/dist/{development/instrumentation-BlrVzjbg.d.ts → production/instrumentation-DvHY1sgY.d.ts} +45 -1
- package/dist/production/lib/types/internal.d.mts +2 -2
- package/dist/production/lib/types/internal.d.ts +2 -2
- package/dist/production/lib/types/internal.js +1 -1
- package/dist/production/lib/types/internal.mjs +1 -1
- package/dist/production/{register-BGQUMCK4.d.ts → register-Bm80E9qL.d.ts} +1 -1
- package/dist/production/{register-DTJJbt1o.d.mts → register-CS_tiXsm.d.mts} +1 -1
- package/dist/production/{router-5fbeEIMQ.d.mts → router-5iOvts3c.d.mts} +45 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
# `react-router`
|
|
2
2
|
|
|
3
|
-
## 7.
|
|
3
|
+
## 7.12.0-pre.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add additional layer of CSRF protection by rejecting submissions to UI routes from external origins. If you need to permit access to specific external origins, you can specify them in the `react-router.config.ts` config `allowedActionOrigins` field. ([#14708](https://github.com/remix-run/react-router/pull/14708))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Fix `generatePath` when used with suffixed params (i.e., "/books/:id.json") ([#14269](https://github.com/remix-run/react-router/pull/14269))
|
|
12
|
+
- Export `UNSAFE_createMemoryHistory` and `UNSAFE_createHashHistory` alongside `UNSAFE_createBrowserHistory` for consistency. These are not intended to be used for new apps but intended to help apps usiong `unstable_HistoryRouter` migrate from v6->v7 so they can adopt the newer APIs. ([#14663](https://github.com/remix-run/react-router/pull/14663))
|
|
13
|
+
- Escape HTML in scroll restoration keys ([#14705](https://github.com/remix-run/react-router/pull/14705))
|
|
14
|
+
- Validate redirect locations ([#14706](https://github.com/remix-run/react-router/pull/14706))
|
|
15
|
+
- [UNSTABLE] Pass `<Scripts nonce>` value through to the underlying `importmap` `script` tag when using `future.unstable_subResourceIntegrity` ([#14675](https://github.com/remix-run/react-router/pull/14675))
|
|
16
|
+
- [UNSTABLE] Add a new `future.unstable_trailingSlashAwareDataRequests` flag to provide consistent behavior of `request.pathname` inside `middleware`, `loader`, and `action` functions on document and data requests when a trailing slash is present in the browser URL. ([#14644](https://github.com/remix-run/react-router/pull/14644))
|
|
17
|
+
|
|
18
|
+
Currently, your HTTP and `request` pathnames would be as follows for `/a/b/c` and `/a/b/c/`
|
|
19
|
+
|
|
20
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname`** |
|
|
21
|
+
| ------------ | ----------------- | ----------------------- |
|
|
22
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
23
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
24
|
+
|
|
25
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname`** |
|
|
26
|
+
| ------------- | ----------------- | ----------------------- |
|
|
27
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
28
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ⚠️ |
|
|
29
|
+
|
|
30
|
+
With this flag enabled, these pathnames will be made consistent though a new `_.data` format for client-side `.data` requests:
|
|
31
|
+
|
|
32
|
+
| URL `/a/b/c` | **HTTP pathname** | **`request` pathname`** |
|
|
33
|
+
| ------------ | ----------------- | ----------------------- |
|
|
34
|
+
| **Document** | `/a/b/c` | `/a/b/c` ✅ |
|
|
35
|
+
| **Data** | `/a/b/c.data` | `/a/b/c` ✅ |
|
|
36
|
+
|
|
37
|
+
| URL `/a/b/c/` | **HTTP pathname** | **`request` pathname`** |
|
|
38
|
+
| ------------- | ------------------ | ----------------------- |
|
|
39
|
+
| **Document** | `/a/b/c/` | `/a/b/c/` ✅ |
|
|
40
|
+
| **Data** | `/a/b/c/_.data` ⬅️ | `/a/b/c/` ✅ |
|
|
41
|
+
|
|
42
|
+
This a bug fix but we are putting it behind an opt-in flag because it has the potential to be a "breaking bug fix" if you are relying on the URL format for any other application or caching logic.
|
|
43
|
+
|
|
44
|
+
Enabling this flag also changes the format of client side `.data` requests from `/_root.data` to `/_.data` when navigating to `/` to align with the new format. This does not impact the `request` pathname which is still `/` in all cases.
|
|
45
|
+
|
|
46
|
+
- Preserve `clientLoader.hydrate=true` when using `<HydratedRouter unstable_instrumentations>` ([#14674](https://github.com/remix-run/react-router/pull/14674))
|
|
47
|
+
|
|
48
|
+
## 7.11.0
|
|
4
49
|
|
|
5
50
|
### Minor Changes
|
|
6
51
|
|
|
@@ -9,10 +54,14 @@
|
|
|
9
54
|
### Patch Changes
|
|
10
55
|
|
|
11
56
|
- add support for throwing redirect Response's at RSC render time ([#14596](https://github.com/remix-run/react-router/pull/14596))
|
|
57
|
+
|
|
12
58
|
- Support for throwing `data()` and Response from server component render phase. Response body is not serialized as async work is not allowed as error encoding phase. If you wish to transmit data to the boundary, throw `data()` instead. ([#14632](https://github.com/remix-run/react-router/pull/14632))
|
|
59
|
+
|
|
13
60
|
- Fix `unstable_useTransitions` prop on `<Router>` component to permit omission for backewards compatibility ([#14646](https://github.com/remix-run/react-router/pull/14646))
|
|
61
|
+
|
|
14
62
|
- `routeRSCServerRequest` replace `fetchServer` with `serverResponse` ([#14597](https://github.com/remix-run/react-router/pull/14597))
|
|
15
|
-
|
|
63
|
+
|
|
64
|
+
- \[UNSTABLE] Add a new `unstable_defaultShouldRevalidate` flag to various APIs to allow opt-ing out of standard revalidation behaviors. ([#14542](https://github.com/remix-run/react-router/pull/14542))
|
|
16
65
|
|
|
17
66
|
If active routes include a `shouldRevalidate` function, then your value will be passed as `defaultShouldRevalidate` in those function so that the route always has the final revalidation determination.
|
|
18
67
|
- `<Form method="post" unstable_defaultShouldRevalidate={false}>`
|
|
@@ -26,6 +75,7 @@
|
|
|
26
75
|
- `setSearchParams(params, { unstable_defaultShouldRevalidate: false })`
|
|
27
76
|
|
|
28
77
|
- Allow redirects to be returned from client side middleware ([#14598](https://github.com/remix-run/react-router/pull/14598))
|
|
78
|
+
|
|
29
79
|
- Handle `dataStrategy` implementations that return insufficient result sets by adding errors for routes without any available result ([#14627](https://github.com/remix-run/react-router/pull/14627))
|
|
30
80
|
|
|
31
81
|
## 7.10.1
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './router-
|
|
2
|
+
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './router-5iOvts3c.mjs';
|
|
3
3
|
|
|
4
4
|
type RSCRouteConfigEntryBase = {
|
|
5
5
|
action?: ActionFunction;
|
|
@@ -138,6 +138,7 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
138
138
|
* @category RSC
|
|
139
139
|
* @mode data
|
|
140
140
|
* @param opts Options
|
|
141
|
+
* @param opts.allowedActionOrigins Origin patterns that are allowed to execute actions.
|
|
141
142
|
* @param opts.basename The basename to use when matching the request.
|
|
142
143
|
* @param opts.createTemporaryReferenceSet A function that returns a temporary
|
|
143
144
|
* reference set for the request, used to track temporary references in the [RSC](https://react.dev/reference/rsc/server-components)
|
|
@@ -167,7 +168,8 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
167
168
|
* that contains the [RSC](https://react.dev/reference/rsc/server-components)
|
|
168
169
|
* data for hydration.
|
|
169
170
|
*/
|
|
170
|
-
declare function matchRSCServerRequest({ createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
171
|
+
declare function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
172
|
+
allowedActionOrigins?: string[];
|
|
171
173
|
createTemporaryReferenceSet: () => unknown;
|
|
172
174
|
basename?: string;
|
|
173
175
|
decodeReply?: DecodeReplyFunction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './
|
|
2
|
+
import { L as Location, C as ClientActionFunction, a as ClientLoaderFunction, b as LinksFunction, M as MetaFunction, S as ShouldRevalidateFunction, P as Params, c as RouterContextProvider, A as ActionFunction, H as HeadersFunction, d as LoaderFunction, e as RouterInit } from './instrumentation-DvHY1sgY.js';
|
|
3
3
|
|
|
4
4
|
type RSCRouteConfigEntryBase = {
|
|
5
5
|
action?: ActionFunction;
|
|
@@ -138,6 +138,7 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
138
138
|
* @category RSC
|
|
139
139
|
* @mode data
|
|
140
140
|
* @param opts Options
|
|
141
|
+
* @param opts.allowedActionOrigins Origin patterns that are allowed to execute actions.
|
|
141
142
|
* @param opts.basename The basename to use when matching the request.
|
|
142
143
|
* @param opts.createTemporaryReferenceSet A function that returns a temporary
|
|
143
144
|
* reference set for the request, used to track temporary references in the [RSC](https://react.dev/reference/rsc/server-components)
|
|
@@ -167,7 +168,8 @@ type LoadServerActionFunction = (id: string) => Promise<Function>;
|
|
|
167
168
|
* that contains the [RSC](https://react.dev/reference/rsc/server-components)
|
|
168
169
|
* data for hydration.
|
|
169
170
|
*/
|
|
170
|
-
declare function matchRSCServerRequest({ createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
171
|
+
declare function matchRSCServerRequest({ allowedActionOrigins, createTemporaryReferenceSet, basename, decodeReply, requestContext, loadServerAction, decodeAction, decodeFormState, onError, request, routes, generateResponse, }: {
|
|
172
|
+
allowedActionOrigins?: string[];
|
|
171
173
|
createTemporaryReferenceSet: () => unknown;
|
|
172
174
|
basename?: string;
|
|
173
175
|
decodeReply?: DecodeReplyFunction;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v7.
|
|
2
|
+
* react-router v7.12.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
withComponentProps,
|
|
52
52
|
withErrorBoundaryProps,
|
|
53
53
|
withHydrateFallbackProps
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-KYKH2NCS.mjs";
|
|
55
55
|
|
|
56
56
|
// lib/dom/ssr/server.tsx
|
|
57
57
|
import * as React from "react";
|
|
@@ -138,7 +138,8 @@ function createRoutesStub(routes, _context) {
|
|
|
138
138
|
frameworkContextRef.current = {
|
|
139
139
|
future: {
|
|
140
140
|
unstable_subResourceIntegrity: future?.unstable_subResourceIntegrity === true,
|
|
141
|
-
v8_middleware: future?.v8_middleware === true
|
|
141
|
+
v8_middleware: future?.v8_middleware === true,
|
|
142
|
+
unstable_trailingSlashAwareDataRequests: future?.unstable_trailingSlashAwareDataRequests === true
|
|
142
143
|
},
|
|
143
144
|
manifest: {
|
|
144
145
|
routes: {},
|
|
@@ -754,6 +755,85 @@ function prependCookies(parentHeaders, childHeaders) {
|
|
|
754
755
|
}
|
|
755
756
|
}
|
|
756
757
|
|
|
758
|
+
// lib/actions.ts
|
|
759
|
+
function throwIfPotentialCSRFAttack(headers, allowedActionOrigins) {
|
|
760
|
+
let originHeader = headers.get("origin");
|
|
761
|
+
let originDomain = typeof originHeader === "string" && originHeader !== "null" ? new URL(originHeader).host : originHeader;
|
|
762
|
+
let host = parseHostHeader(headers);
|
|
763
|
+
if (originDomain && (!host || originDomain !== host.value)) {
|
|
764
|
+
if (!isAllowedOrigin(originDomain, allowedActionOrigins)) {
|
|
765
|
+
if (host) {
|
|
766
|
+
throw new Error(
|
|
767
|
+
`${host.type} header does not match \`origin\` header from a forwarded action request. Aborting the action.`
|
|
768
|
+
);
|
|
769
|
+
} else {
|
|
770
|
+
throw new Error(
|
|
771
|
+
"`x-forwarded-host` or `host` headers are not provided. One of these is needed to compare the `origin` header from a forwarded action request. Aborting the action."
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
function matchWildcardDomain(domain, pattern) {
|
|
778
|
+
const domainParts = domain.split(".");
|
|
779
|
+
const patternParts = pattern.split(".");
|
|
780
|
+
if (patternParts.length < 1) {
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
if (domainParts.length < patternParts.length) {
|
|
784
|
+
return false;
|
|
785
|
+
}
|
|
786
|
+
if (patternParts.length === 1 && (patternParts[0] === "*" || patternParts[0] === "**")) {
|
|
787
|
+
return false;
|
|
788
|
+
}
|
|
789
|
+
while (patternParts.length) {
|
|
790
|
+
const patternPart = patternParts.pop();
|
|
791
|
+
const domainPart = domainParts.pop();
|
|
792
|
+
switch (patternPart) {
|
|
793
|
+
case "": {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
case "*": {
|
|
797
|
+
if (domainPart) {
|
|
798
|
+
continue;
|
|
799
|
+
} else {
|
|
800
|
+
return false;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
case "**": {
|
|
804
|
+
if (patternParts.length > 0) {
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
return domainPart !== void 0;
|
|
808
|
+
}
|
|
809
|
+
case void 0:
|
|
810
|
+
default: {
|
|
811
|
+
if (domainPart !== patternPart) {
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
return domainParts.length === 0;
|
|
818
|
+
}
|
|
819
|
+
function isAllowedOrigin(originDomain, allowedActionOrigins = []) {
|
|
820
|
+
return allowedActionOrigins.some(
|
|
821
|
+
(allowedOrigin) => allowedOrigin && (allowedOrigin === originDomain || matchWildcardDomain(originDomain, allowedOrigin))
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
function parseHostHeader(headers) {
|
|
825
|
+
let forwardedHostHeader = headers.get("x-forwarded-host");
|
|
826
|
+
let forwardedHostValue = forwardedHostHeader?.split(",")[0]?.trim();
|
|
827
|
+
let hostHeader = headers.get("host");
|
|
828
|
+
return forwardedHostValue ? {
|
|
829
|
+
type: "x-forwarded-host",
|
|
830
|
+
value: forwardedHostValue
|
|
831
|
+
} : hostHeader ? {
|
|
832
|
+
type: "host",
|
|
833
|
+
value: hostHeader
|
|
834
|
+
} : void 0;
|
|
835
|
+
}
|
|
836
|
+
|
|
757
837
|
// lib/server-runtime/single-fetch.ts
|
|
758
838
|
var SERVER_NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([
|
|
759
839
|
...NO_BODY_STATUS_CODES,
|
|
@@ -761,6 +841,10 @@ var SERVER_NO_BODY_STATUS_CODES = /* @__PURE__ */ new Set([
|
|
|
761
841
|
]);
|
|
762
842
|
async function singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) {
|
|
763
843
|
try {
|
|
844
|
+
throwIfPotentialCSRFAttack(
|
|
845
|
+
request.headers,
|
|
846
|
+
Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []
|
|
847
|
+
);
|
|
764
848
|
let handlerRequest = new Request(handlerUrl, {
|
|
765
849
|
method: request.method,
|
|
766
850
|
body: request.body,
|
|
@@ -1041,13 +1125,21 @@ function derive(build, mode) {
|
|
|
1041
1125
|
let url = new URL(request.url);
|
|
1042
1126
|
let normalizedBasename = build.basename || "/";
|
|
1043
1127
|
let normalizedPath = url.pathname;
|
|
1044
|
-
if (
|
|
1045
|
-
normalizedPath
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1128
|
+
if (build.future.unstable_trailingSlashAwareDataRequests) {
|
|
1129
|
+
if (normalizedPath.endsWith("/_.data")) {
|
|
1130
|
+
normalizedPath = normalizedPath.replace(/_.data$/, "");
|
|
1131
|
+
} else {
|
|
1132
|
+
normalizedPath = normalizedPath.replace(/\.data$/, "");
|
|
1133
|
+
}
|
|
1134
|
+
} else {
|
|
1135
|
+
if (stripBasename(normalizedPath, normalizedBasename) === "/_root.data") {
|
|
1136
|
+
normalizedPath = normalizedBasename;
|
|
1137
|
+
} else if (normalizedPath.endsWith(".data")) {
|
|
1138
|
+
normalizedPath = normalizedPath.replace(/\.data$/, "");
|
|
1139
|
+
}
|
|
1140
|
+
if (stripBasename(normalizedPath, normalizedBasename) !== "/" && normalizedPath.endsWith("/")) {
|
|
1141
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
1142
|
+
}
|
|
1051
1143
|
}
|
|
1052
1144
|
let isSpaMode = getBuildTimeHeader(request, "X-React-Router-SPA-Mode") === "yes";
|
|
1053
1145
|
if (!build.ssr) {
|
|
@@ -1303,6 +1395,12 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
|
|
|
1303
1395
|
}
|
|
1304
1396
|
async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, isSpaMode, criticalCss) {
|
|
1305
1397
|
try {
|
|
1398
|
+
if (request.method === "POST") {
|
|
1399
|
+
throwIfPotentialCSRFAttack(
|
|
1400
|
+
request.headers,
|
|
1401
|
+
Array.isArray(build.allowedActionOrigins) ? build.allowedActionOrigins : []
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1306
1404
|
let result = await staticHandler.query(request, {
|
|
1307
1405
|
requestContext: loadContext,
|
|
1308
1406
|
generateMiddlewareResponse: build.future.v8_middleware ? async (query) => {
|
|
@@ -2274,7 +2372,9 @@ function RSCStaticRouter({ getPayload }) {
|
|
|
2274
2372
|
// These flags have no runtime impact so can always be false. If we add
|
|
2275
2373
|
// flags that drive runtime behavior they'll need to be proxied through.
|
|
2276
2374
|
v8_middleware: false,
|
|
2277
|
-
unstable_subResourceIntegrity: false
|
|
2375
|
+
unstable_subResourceIntegrity: false,
|
|
2376
|
+
unstable_trailingSlashAwareDataRequests: true
|
|
2377
|
+
// always on for RSC
|
|
2278
2378
|
},
|
|
2279
2379
|
isSpaMode: false,
|
|
2280
2380
|
ssr: true,
|