Skip to content

[DevTools] Enable support for the React DevTools Client to connect to different host/port/path #603

Closed
everettbu wants to merge 1 commit into
mainfrom
react-devtools-path
Closed

[DevTools] Enable support for the React DevTools Client to connect to different host/port/path #603
everettbu wants to merge 1 commit into
mainfrom
react-devtools-path

Conversation

@everettbu

@everettbu everettbu commented Feb 23, 2026

Copy link
Copy Markdown

Mirror of facebook/react#35886
Original author: fullstackhacker


Summary

This enables routing the React Dev Tools through a remote server by being able to specify host, port, and path for the client to connect to. Basically allowing the React Dev Tools server to have the client connect elsewhere.

This setups a clientOptions which can be set up through environment variables when starting the React Dev Tools server.

This change shouldn't affect the traditional usage for React Dev Tools.

EDIT: the additional change was moved to another PR

How did you test this change?

Run React DevTools with

$ REACT_DEVTOOLS_CLIENT_HOST=<MY_HOST> REACT_DEVTOOLS_CLIENT_PORT=443 REACT_DEVTOOLS_CLIENT_USE_HTTPS=true REACT_DEVTOOLS_PATH=/__react_devtools__/ yarn start

Confirm that my application connects to the local React Dev Tools server/instance/electron app through my remote server.

@greptile-apps

greptile-apps Bot commented Feb 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds support for routing the React DevTools client through a remote server (e.g., a reverse proxy) by introducing path, clientOptions (host, port, useHttps), and corresponding environment variables (REACT_DEVTOOLS_PATH, REACT_DEVTOOLS_CLIENT_HOST, REACT_DEVTOOLS_CLIENT_PORT, REACT_DEVTOOLS_CLIENT_USE_HTTPS). The changes span the backend connection logic (backend.js), the standalone server (standalone.js), the Electron preload/app layer, and documentation.

  • backend.js gains a path option on connectToDevTools, correctly normalized with a leading / and appended to the WebSocket URI.
  • standalone.js gains path and clientOptions parameters on startServer, with client-facing overrides injected into the served script. The retry-on-error handlers now correctly forward all arguments (previously only port was passed).
  • preload.js reads the new environment variables and passes them through to app.html.
  • app.html constructs display URLs and passes clientOptions to startServer. The path is not normalized with a leading / here (unlike backend.js), which can produce broken display URLs. The "by IP" URL also becomes misleading when client overrides point to a remote proxy.

Confidence Score: 4/5

  • This PR is safe to merge with minor display URL issues in app.html that don't affect core functionality.
  • The core logic for path and client overrides is correct. The WebSocket connection, served script generation, and env var handling all work properly. Two minor issues in app.html's display URL construction (missing path normalization and misleading "by IP" URL with client overrides) prevent a perfect score, but neither causes runtime failures in the DevTools connection itself.
  • Pay close attention to packages/react-devtools/app.html — the display URL construction has a path normalization gap and a misleading "by IP" URL when client overrides are active.

Important Files Changed

Filename Overview
packages/react-devtools-core/src/backend.js Adds path option to ConnectOptions and connectToDevTools, correctly normalizing it with a leading / and appending it to the WebSocket URI. Clean implementation.
packages/react-devtools-core/src/standalone.js Adds path and clientOptions parameters to startServer, fixes retry handlers to pass all arguments, and serves client-facing overrides in the generated script. String interpolation concern was already flagged in a previous review thread.
packages/react-devtools/preload.js Reads new environment variables (REACT_DEVTOOLS_PATH, REACT_DEVTOOLS_CLIENT_HOST, REACT_DEVTOOLS_CLIENT_PORT, REACT_DEVTOOLS_CLIENT_USE_HTTPS) and returns them from readEnv(). Correct use of undefined fallbacks and numeric coercion.
packages/react-devtools/app.html Consumes new env values to construct display URLs and pass clientOptions to startServer. The path is not normalized with a leading / (unlike backend.js), and the "by IP" URL is misleading when client overrides point to a remote proxy.
packages/react-devtools-core/README.md Documentation updates for path, clientOptions, env vars, and a reverse proxy example. Accurate and well-structured.
packages/react-devtools/README.md Adds environment variable reference table and reverse proxy example. Replaces terse description with comprehensive documentation.

Last reviewed commit: d987502

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +396 to +398
`Backend.connectToDevTools({port: ${clientPort}, host: '${clientHost}', useHttps: ${
clientUseHttps ? 'true' : 'false'
}${path != null ? `, path: '${path}'` : ''}});\n` +

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsanitized string interpolation into generated JS

clientHost and path are interpolated directly into single-quoted JavaScript string literals without escaping. If either value contains a single quote or backslash, it will break the generated script (or worse, allow code injection if startServer is ever called with untrusted input).

The pre-existing host interpolation had the same issue, but this PR extends the pattern to two new parameters. Consider using JSON.stringify() for safe embedding, which is already used for componentFiltersString on line 395:

Suggested change
`Backend.connectToDevTools({port: ${clientPort}, host: '${clientHost}', useHttps: ${
clientUseHttps ? 'true' : 'false'
}${path != null ? `, path: '${path}'` : ''}});\n` +
`Backend.connectToDevTools({port: ${clientPort}, host: ${JSON.stringify(clientHost)}, useHttps: ${
clientUseHttps ? 'true' : 'false'
}${path != null ? `, path: ${JSON.stringify(path)}` : ''}});\n` +
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react-devtools-core/src/standalone.js
Line: 396-398

Comment:
**Unsanitized string interpolation into generated JS**

`clientHost` and `path` are interpolated directly into single-quoted JavaScript string literals without escaping. If either value contains a single quote or backslash, it will break the generated script (or worse, allow code injection if `startServer` is ever called with untrusted input).

The pre-existing `host` interpolation had the same issue, but this PR extends the pattern to two new parameters. Consider using `JSON.stringify()` for safe embedding, which is already used for `componentFiltersString` on line 395:

```suggestion
        `Backend.connectToDevTools({port: ${clientPort}, host: ${JSON.stringify(clientHost)}, useHttps: ${
          clientUseHttps ? 'true' : 'false'
        }${path != null ? `, path: ${JSON.stringify(path)}` : ''}});\n` +
```

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +171 to +173
const pathStr = path != null ? path : '';
const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;
const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing leading / normalization for path

backend.js:112 normalizes the path by prepending / if it's missing, but this display URL construction does not. If a user sets REACT_DEVTOOLS_PATH=__react_devtools__/ (without a leading /), the display URL becomes http://localhost:8097__react_devtools__/ — a broken URL with no path separator.

Consider normalizing pathStr the same way backend.js does:

Suggested change
const pathStr = path != null ? path : '';
const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;
const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;
const pathStr = path != null ? (path !== '' && !path.startsWith('/') ? '/' + path : path) : '';
const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;
const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react-devtools/app.html
Line: 171-173

Comment:
**Missing leading `/` normalization for `path`**

`backend.js:112` normalizes the `path` by prepending `/` if it's missing, but this display URL construction does not. If a user sets `REACT_DEVTOOLS_PATH=__react_devtools__/` (without a leading `/`), the display URL becomes `http://localhost:8097__react_devtools__/` — a broken URL with no path separator.

Consider normalizing `pathStr` the same way `backend.js` does:

```suggestion
      const pathStr = path != null ? (path !== '' && !path.startsWith('/') ? '/' + path : path) : '';
      const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;
      const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +166 to +173
const effectiveHost = clientHost != null ? clientHost : host;
const effectivePort = clientPort != null ? clientPort : port;
const effectiveUseHttps = clientUseHttps != null ? clientUseHttps : useHttps;
const effectiveProtocol = effectiveUseHttps ? 'https' : 'http';
const defaultPort = (effectivePort === 443 && effectiveUseHttps) || (effectivePort === 80 && !effectiveUseHttps);
const pathStr = path != null ? path : '';
const server = defaultPort ? `${effectiveProtocol}://${effectiveHost}${pathStr}` : `${effectiveProtocol}://${effectiveHost}:${effectivePort}${pathStr}`;
const serverIp = defaultPort ? `${effectiveProtocol}://${localIp}${pathStr}` : `${effectiveProtocol}://${localIp}:${effectivePort}${pathStr}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"By IP" display URL is misleading with client overrides

When client overrides are set (e.g., REACT_DEVTOOLS_CLIENT_HOST=remote.example.com, REACT_DEVTOOLS_CLIENT_PORT=443, REACT_DEVTOOLS_CLIENT_USE_HTTPS=true), serverIp becomes something like https://192.168.1.5:443/__react_devtools__/. This mixes the local IP with the remote proxy's protocol/port, producing a URL that won't work.

Consider either falling back to the server's own port/protocol for the IP-based URL (since that represents the local server), or hiding the "by IP" suggestion entirely when clientHost is set.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react-devtools/app.html
Line: 166-173

Comment:
**"By IP" display URL is misleading with client overrides**

When client overrides are set (e.g., `REACT_DEVTOOLS_CLIENT_HOST=remote.example.com`, `REACT_DEVTOOLS_CLIENT_PORT=443`, `REACT_DEVTOOLS_CLIENT_USE_HTTPS=true`), `serverIp` becomes something like `https://192.168.1.5:443/__react_devtools__/`. This mixes the local IP with the remote proxy's protocol/port, producing a URL that won't work.

Consider either falling back to the server's own port/protocol for the IP-based URL (since that represents the local server), or hiding the "by IP" suggestion entirely when `clientHost` is set.

How can I resolve this? If you propose a fix, please make it concise.

@everettbu

Copy link
Copy Markdown
Author

Upstream PR was closed or merged. Code is synced via branch mirror.

@everettbu everettbu closed this Feb 24, 2026
@everettbu
everettbu deleted the react-devtools-path branch February 24, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants