Add SSL support to React devtools standalone (#19191)

Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
This commit is contained in:
Ittai Baratz 2020-07-06 07:09:41 -07:00 committed by GitHub
parent 65c137768a
commit 1cbaf48889
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 8 deletions

View File

@ -21,6 +21,7 @@ Be sure to run this function *before* importing e.g. `react`, `react-dom`, `reac
The `config` object may contain:
* `host: string` (defaults to "localhost") - Websocket will connect to this host.
* `port: number` (defaults to `8097`) - Websocket will connect to this port.
* `useHttps: boolean` (defaults to `false`) - Websocked should use a secure protocol (wss).
* `websocket: Websocket` - Custom websocket to use. Overrides `host` and `port` settings if provided.
* `resolveRNStyle: (style: number) => ?Object` - Used by the React Native style plug-in.
* `isAppActive: () => boolean` - If provided, DevTools will poll this method and wait until it returns true before connecting to React.
@ -38,6 +39,24 @@ require("react-devtools-core/standalone")
.startServer(port);
```
Renders DevTools interface into a DOM node over SSL using a custom host name (Default is localhost).
```js
const host = 'dev.server.com';
const options = {
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};
require("react-devtools-core/standalone")
.setContentDOMNode(document.getElementById("container"))
.setStatusListener(status => {
// This callback is optional...
})
.startServer(port, host, options);
```
Reference the `react-devtools` package for a complete integration example.
## Development

View File

@ -24,6 +24,7 @@ type ConnectOptions = {
host?: string,
nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,
port?: number,
useHttps?: boolean,
resolveRNStyle?: ResolveNativeStyle,
isAppActive?: () => boolean,
websocket?: ?WebSocket,
@ -55,12 +56,14 @@ export function connectToDevTools(options: ?ConnectOptions) {
const {
host = 'localhost',
nativeStyleEditorValidAttributes,
useHttps = false,
port = 8097,
websocket,
resolveRNStyle = null,
isAppActive = () => true,
} = options || {};
const protocol = useHttps ? 'wss' : 'ws';
let retryTimeoutID: TimeoutID | null = null;
function scheduleRetry() {
@ -80,7 +83,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
let bridge: BackendBridge | null = null;
const messageListeners = [];
const uri = 'ws://' + host + ':' + port;
const uri = protocol + '://' + host + ':' + port;
// If existing websocket is passed, use it.
// This is necessary to support our custom integrations.

View File

@ -242,8 +242,20 @@ function connectToSocket(socket: WebSocket) {
};
}
function startServer(port?: number = 8097) {
const httpServer = require('http').createServer();
type ServerOptions = {
key?: string,
cert?: string,
};
function startServer(
port?: number = 8097,
host?: string = 'localhost',
httpsOptions?: ServerOptions,
) {
const useHttps = !!httpsOptions;
const httpServer = useHttps
? require('https').createServer(httpsOptions)
: require('http').createServer();
const server = new Server({server: httpServer});
let connected: WebSocket | null = null;
server.on('connection', (socket: WebSocket) => {
@ -298,7 +310,9 @@ function startServer(port?: number = 8097) {
'\n;' +
backendFile.toString() +
'\n;' +
'ReactDevToolsBackend.connectToDevTools();',
`ReactDevToolsBackend.connectToDevTools({port: ${port}, host: '${host}', useHttps: ${
useHttps ? 'true' : 'false'
}});`,
);
});

View File

@ -145,12 +145,33 @@
</div>
</div>
<script>
const fs = require('fs');
let options;
let useHttps = false;
try {
if (process.env.KEY && process.env.CERT) {
options.key = fs.readFileSync(process.env.KEY);
options.cert = fs.readFileSync(process.env.CERT);
useHttps = true;
}
} catch (err) {
console.error('Failed to process SSL options - ', err);
options = undefined;
}
const {clipboard} = require("electron");
const port = process.env.PORT || 8097;
const host = process.env.HOST || 'localhost';
const protocol = useHttps ? 'https' : 'http';
const port = Number(process.env.PORT || 8097);
const localIp = require("ip").address();
const defaultPort = (port === 443 && useHttps) || (port === 80 && !useHttps);
const server = defaultPort ? `${protocol}://${host}` : `${protocol}://${host}:${port}`;
const serverIp = defaultPort ? `${protocol}://${localIp}` : `${protocol}://${localIp}:${port}`;
const $ = document.querySelector.bind(document);
const $promptDiv = $("#box-content-prompt");
const $confirmationDiv = $("#box-content-confirmation");
let timeoutID;
function selectAllAndCopy(event) {
@ -184,12 +205,12 @@
});
const $localhost = $("#localhost");
$localhost.innerText = `<script src="http://localhost:${port}"></` + 'script>';
$localhost.innerText = `<script src="${server}"></` + 'script>';
$localhost.addEventListener('click', selectAllAndCopy);
$localhost.addEventListener('focus', selectAllAndCopy);
const $byIp = $("#byip");
$byIp.innerText = `<script src="http://${localIp}:${port}"></` + 'script>';
$byIp.innerText = `<script src="${serverIp}"></` + 'script>';
$byIp.addEventListener('click', selectAllAndCopy);
$byIp.addEventListener('focus', selectAllAndCopy);
@ -211,7 +232,7 @@
element.innerText = status;
}
})
.startServer(port);
.startServer(port, host, options);
</script>
</body>
</html>