Skip to content

Commit 1cbaf48

Browse files
ittaibaratzbvaughn
andauthored
Add SSL support to React devtools standalone (facebook#19191)
Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
1 parent 65c1377 commit 1cbaf48

File tree

4 files changed

+65
-8
lines changed

4 files changed

+65
-8
lines changed

packages/react-devtools-core/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Be sure to run this function *before* importing e.g. `react`, `react-dom`, `reac
2121
The `config` object may contain:
2222
* `host: string` (defaults to "localhost") - Websocket will connect to this host.
2323
* `port: number` (defaults to `8097`) - Websocket will connect to this port.
24+
* `useHttps: boolean` (defaults to `false`) - Websocked should use a secure protocol (wss).
2425
* `websocket: Websocket` - Custom websocket to use. Overrides `host` and `port` settings if provided.
2526
* `resolveRNStyle: (style: number) => ?Object` - Used by the React Native style plug-in.
2627
* `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")
3839
.startServer(port);
3940
```
4041

42+
Renders DevTools interface into a DOM node over SSL using a custom host name (Default is localhost).
43+
44+
```js
45+
const host = 'dev.server.com';
46+
const options = {
47+
key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
48+
cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
49+
};
50+
51+
52+
require("react-devtools-core/standalone")
53+
.setContentDOMNode(document.getElementById("container"))
54+
.setStatusListener(status => {
55+
// This callback is optional...
56+
})
57+
.startServer(port, host, options);
58+
```
59+
4160
Reference the `react-devtools` package for a complete integration example.
4261

4362
## Development

packages/react-devtools-core/src/backend.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type ConnectOptions = {
2424
host?: string,
2525
nativeStyleEditorValidAttributes?: $ReadOnlyArray<string>,
2626
port?: number,
27+
useHttps?: boolean,
2728
resolveRNStyle?: ResolveNativeStyle,
2829
isAppActive?: () => boolean,
2930
websocket?: ?WebSocket,
@@ -55,12 +56,14 @@ export function connectToDevTools(options: ?ConnectOptions) {
5556
const {
5657
host = 'localhost',
5758
nativeStyleEditorValidAttributes,
59+
useHttps = false,
5860
port = 8097,
5961
websocket,
6062
resolveRNStyle = null,
6163
isAppActive = () => true,
6264
} = options || {};
6365

66+
const protocol = useHttps ? 'wss' : 'ws';
6467
let retryTimeoutID: TimeoutID | null = null;
6568

6669
function scheduleRetry() {
@@ -80,7 +83,7 @@ export function connectToDevTools(options: ?ConnectOptions) {
8083
let bridge: BackendBridge | null = null;
8184

8285
const messageListeners = [];
83-
const uri = 'ws://' + host + ':' + port;
86+
const uri = protocol + '://' + host + ':' + port;
8487

8588
// If existing websocket is passed, use it.
8689
// This is necessary to support our custom integrations.

packages/react-devtools-core/src/standalone.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,20 @@ function connectToSocket(socket: WebSocket) {
242242
};
243243
}
244244

245-
function startServer(port?: number = 8097) {
246-
const httpServer = require('http').createServer();
245+
type ServerOptions = {
246+
key?: string,
247+
cert?: string,
248+
};
249+
250+
function startServer(
251+
port?: number = 8097,
252+
host?: string = 'localhost',
253+
httpsOptions?: ServerOptions,
254+
) {
255+
const useHttps = !!httpsOptions;
256+
const httpServer = useHttps
257+
? require('https').createServer(httpsOptions)
258+
: require('http').createServer();
247259
const server = new Server({server: httpServer});
248260
let connected: WebSocket | null = null;
249261
server.on('connection', (socket: WebSocket) => {
@@ -298,7 +310,9 @@ function startServer(port?: number = 8097) {
298310
'\n;' +
299311
backendFile.toString() +
300312
'\n;' +
301-
'ReactDevToolsBackend.connectToDevTools();',
313+
`ReactDevToolsBackend.connectToDevTools({port: ${port}, host: '${host}', useHttps: ${
314+
useHttps ? 'true' : 'false'
315+
}});`,
302316
);
303317
});
304318

packages/react-devtools/app.html

+25-4
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,33 @@
145145
</div>
146146
</div>
147147
<script>
148+
const fs = require('fs');
149+
let options;
150+
let useHttps = false;
151+
152+
try {
153+
if (process.env.KEY && process.env.CERT) {
154+
options.key = fs.readFileSync(process.env.KEY);
155+
options.cert = fs.readFileSync(process.env.CERT);
156+
useHttps = true;
157+
}
158+
} catch (err) {
159+
console.error('Failed to process SSL options - ', err);
160+
options = undefined;
161+
}
162+
148163
const {clipboard} = require("electron");
149-
const port = process.env.PORT || 8097;
164+
const host = process.env.HOST || 'localhost';
165+
const protocol = useHttps ? 'https' : 'http';
166+
const port = Number(process.env.PORT || 8097);
150167
const localIp = require("ip").address();
168+
const defaultPort = (port === 443 && useHttps) || (port === 80 && !useHttps);
169+
const server = defaultPort ? `${protocol}://${host}` : `${protocol}://${host}:${port}`;
170+
const serverIp = defaultPort ? `${protocol}://${localIp}` : `${protocol}://${localIp}:${port}`;
151171
const $ = document.querySelector.bind(document);
152172
const $promptDiv = $("#box-content-prompt");
153173
const $confirmationDiv = $("#box-content-confirmation");
174+
154175
let timeoutID;
155176

156177
function selectAllAndCopy(event) {
@@ -184,12 +205,12 @@
184205
});
185206

186207
const $localhost = $("#localhost");
187-
$localhost.innerText = `<script src="http://localhost:${port}"></` + 'script>';
208+
$localhost.innerText = `<script src="${server}"></` + 'script>';
188209
$localhost.addEventListener('click', selectAllAndCopy);
189210
$localhost.addEventListener('focus', selectAllAndCopy);
190211

191212
const $byIp = $("#byip");
192-
$byIp.innerText = `<script src="http://${localIp}:${port}"></` + 'script>';
213+
$byIp.innerText = `<script src="${serverIp}"></` + 'script>';
193214
$byIp.addEventListener('click', selectAllAndCopy);
194215
$byIp.addEventListener('focus', selectAllAndCopy);
195216

@@ -211,7 +232,7 @@
211232
element.innerText = status;
212233
}
213234
})
214-
.startServer(port);
235+
.startServer(port, host, options);
215236
</script>
216237
</body>
217238
</html>

0 commit comments

Comments
 (0)