Reproduction
Since Pull #15419 (@brophdawg11)
react-router dev always computes wrong req.url, it assumes protocol = http
Details follows:
In Fetcher action I get error in development mode
Error: Bad Request
at singleFetchAction (file:///Users/node_modules/react-router/dist/development/lib/server-runtime/single-fetch.js:27:44)
at handleSingleFetchRequest (file:///Users/node_modules/react-router/dist/development/lib/server-runtime/server.js:203:50)
at requestHandler (file:///Users/node_modules/react-router/dist/development/lib/server-runtime/server.js:107:21)
at requestHandler (file:///Users/node_modules/react-router/dist/development/lib/server-runtime/server.js:173:10)
at nodeHandler (file:///Users/node_modules/@react-router/dev/dist/vite.js:1661:43)
at async file:///Users/node_modules/@react-router/dev/dist/vite.js:1663:8
Further debugging it
singleFetchAction -> /Users/node_modules/react-router/dist/development/lib/server-runtime/single-fetch.js
the error is thrown due to throwIfPotentialCSRFAttack
throwIfPotentialCSRFAttack -> /Users/node_modules/react-router/dist/development/lib/actions.js is thrown due to
let originMatchesRequest = originUrl ? originUrl.origin === requestUrl.origin : originDomain === requestUrl.host;
if (originDomain && !originMatchesRequest) {
if (!isAllowedOrigin(originDomain, allowedActionOrigins)) throw new Error("The `request.url` origin does not match `origin` header from a forwarded action request. Aborting the action.");
}
Here originMatchesRequest is false, since, originUrl.origin & requestUrl.origin mismatches.
In my case, values determined are:
originUrl.origin: 'https://demo.example.com' & requestUrl.origin: 'http://demo.example.com'
My Headers are:
...
host: 'demo.example.com',
'x-real-ip': '127.0.0.1',
'x-forwarded-for': '127.0.0.1',
'x-forwarded-host': 'demo.example.com',
'x-forwarded-port': '443',
'x-forwarded-proto': 'https',
'content-length': '51',
pragma: 'no-cache',
'cache-control': 'no-cache',
'sec-ch-ua-platform': '"macOS"',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36 Edg/151.0.0.0',
'sec-ch-ua': '"Not=A?Brand";v="99", "Microsoft Edge";v="151", "Chromium";v="151"',
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8',
'sec-ch-ua-mobile': '?0',
accept: '*/*',
origin: 'https://demo.example.com',
...
To find the cause of wrong protocol (http instead of https), i traced futher,
In file, /node_modules/@react-router/dev/dist/vite.js
function -> reactRouterVitePlugin -> line let req = await fromNodeRequest(nodeReq, nodeRes);
and in same file, function fromNodeRequest is defined as
async function fromNodeRequest(nodeReq, nodeRes) {
invariant(nodeReq.originalUrl, "Expected `nodeReq.originalUrl` to be defined");
nodeReq.url = nodeReq.originalUrl;
return createRequest(nodeReq, nodeRes);
}
It calls createRequest with only 2 arguments, createRequest of /node_modules/@remix-run/node-fetch-server/dist/lib/request-listener.js expects third argument options which has many property including protocol, trustproxy, etc. which is not passed when calling this function.
Hence, options is always undefined and the url returned by this createRequest always have url starting with "http" and it throws error due to cors. There is no way to fix this in development mode.
Kindly check and resolve this.
System Info
System:
OS: macOS 26.5.2
CPU: (10) arm64 Apple M2 Pro
Memory: 93.33 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.22.3 - /Users/.nvm/versions/node/v22.22.3/bin/node
Yarn: 1.22.22 - /Users/.nvm/versions/node/v22.22.3/bin/yarn
npm: 10.9.8 - /Users/.nvm/versions/node/v22.22.3/bin/npm
Browsers:
Chrome: 152.0.7977.64
Edge: 152.0.4191.53
Firefox: 154.0.1
Safari: 26.5.2
npmPackages:
@react-router/dev: ^8.3.1 => 8.3.1
@react-router/express: ^8.3.1 => 8.3.1
@react-router/fs-routes: ^8.3.1 => 8.3.1
@react-router/node: ^8.3.1 => 8.3.1
react-router: ^8.3.0 => 8.3.1
vite: ^8.2.2 => 8.2.2
Used Package Manager
npm
Expected Behavior
react-reouter dev should respect protocol "https" of request url, it should allow "trust proxy" and header "X-Forwarded-Proto"
Actual Behavior
react-router dev always computes wrong req.url, it assumes protocol = http
Reproduction
Since Pull #15419 (@brophdawg11)
react-router devalways computes wrong req.url, it assumes protocol = httpDetails follows:
In Fetcher action I get error in development mode
Further debugging it
singleFetchAction -> /Users/node_modules/react-router/dist/development/lib/server-runtime/single-fetch.js
the error is thrown due to throwIfPotentialCSRFAttack
throwIfPotentialCSRFAttack -> /Users/node_modules/react-router/dist/development/lib/actions.js is thrown due to
Here originMatchesRequest is false, since, originUrl.origin & requestUrl.origin mismatches.
In my case, values determined are:
originUrl.origin: 'https://demo.example.com' & requestUrl.origin: 'http://demo.example.com'
My Headers are:
To find the cause of wrong protocol (http instead of https), i traced futher,
In file, /node_modules/@react-router/dev/dist/vite.js
function -> reactRouterVitePlugin -> line
let req = await fromNodeRequest(nodeReq, nodeRes);and in same file, function fromNodeRequest is defined as
It calls
createRequestwith only 2 arguments,createRequestof /node_modules/@remix-run/node-fetch-server/dist/lib/request-listener.js expects third argumentoptionswhich has many property including protocol, trustproxy, etc. which is not passed when calling this function.Hence,
optionsis always undefined and the url returned by this createRequest always have url starting with "http" and it throws error due to cors. There is no way to fix this in development mode.Kindly check and resolve this.
System Info
System: OS: macOS 26.5.2 CPU: (10) arm64 Apple M2 Pro Memory: 93.33 MB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 22.22.3 - /Users/.nvm/versions/node/v22.22.3/bin/node Yarn: 1.22.22 - /Users/.nvm/versions/node/v22.22.3/bin/yarn npm: 10.9.8 - /Users/.nvm/versions/node/v22.22.3/bin/npm Browsers: Chrome: 152.0.7977.64 Edge: 152.0.4191.53 Firefox: 154.0.1 Safari: 26.5.2 npmPackages: @react-router/dev: ^8.3.1 => 8.3.1 @react-router/express: ^8.3.1 => 8.3.1 @react-router/fs-routes: ^8.3.1 => 8.3.1 @react-router/node: ^8.3.1 => 8.3.1 react-router: ^8.3.0 => 8.3.1 vite: ^8.2.2 => 8.2.2Used Package Manager
npm
Expected Behavior
react-reouter devshould respect protocol "https" of request url, it should allow "trust proxy" and header "X-Forwarded-Proto"Actual Behavior
react-router devalways computes wrong req.url, it assumes protocol = http