Skip to content

Commit 34a7526

Browse files
motiz88facebook-github-bot
authored andcommitted
Remove host/port params, construct WebSocket URL from /json request (#39394)
Summary: Pull Request resolved: #39394 * Constructs DevTools frontend WebSocket URLs with a client-accessible host, port and scheme derived from the initiating HTTP request (`/json` or `/open-debugger`), instead of from the static `host` and `port` parameters provided to `createDevMiddleware`. This results in more proxy-safe behaviour. * Removes the now-unused `host` and `port` parameters from `createDevMiddleware`. Changelog: [Internal] Reviewed By: huntie Differential Revision: D49158227 fbshipit-source-id: ec61d98458e5d5afba4eb937b84ff65071495cc9
1 parent 1187720 commit 34a7526

File tree

6 files changed

+56
-30
lines changed

6 files changed

+56
-30
lines changed

packages/community-cli-plugin/src/commands/start/runServer.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ async function runServer(
113113
watchFolders,
114114
});
115115
const {middleware, websocketEndpoints} = createDevMiddleware({
116-
host,
117-
port,
118116
projectRoot,
119117
logger,
120118
unstable_experiments: {

packages/dev-middleware/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ function myDevServerImpl(args) {
1515
...
1616

1717
const {middleware, websocketEndpoints} = createDevMiddleware({
18-
host: args.host,
19-
port: metroConfig.server.port,
2018
projectRoot: metroConfig.projectRoot,
2119
logger,
2220
});

packages/dev-middleware/src/createDevMiddleware.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import InspectorProxy from './inspector-proxy/InspectorProxy';
2525
import DefaultBrowserLauncher from './utils/DefaultBrowserLauncher';
2626

2727
type Options = $ReadOnly<{
28-
host: string,
29-
port: number,
3028
projectRoot: string,
3129
logger?: Logger,
3230
unstable_browserLauncher?: BrowserLauncher,
@@ -40,8 +38,6 @@ type DevMiddlewareAPI = $ReadOnly<{
4038
}>;
4139

4240
export default function createDevMiddleware({
43-
host,
44-
port,
4541
projectRoot,
4642
logger,
4743
unstable_browserLauncher = DefaultBrowserLauncher,
@@ -76,9 +72,7 @@ export default function createDevMiddleware({
7672

7773
return {
7874
middleware,
79-
websocketEndpoints: inspectorProxy.createWebSocketListeners(
80-
`${host}:${port}`,
81-
),
75+
websocketEndpoints: inspectorProxy.createWebSocketListeners(),
8276
};
8377
}
8478

packages/dev-middleware/src/inspector-proxy/InspectorProxy.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type {IncomingMessage, ServerResponse} from 'http';
2222
import url from 'url';
2323
import WS from 'ws';
2424
import Device from './Device';
25+
import getDevServerUrl from '../utils/getDevServerUrl';
2526

2627
const debug = require('debug')('Metro:InspectorProxy');
2728

@@ -46,11 +47,6 @@ export default class InspectorProxy {
4647
// Internal counter for device IDs -- just gets incremented for each new device.
4748
_deviceCounter: number = 0;
4849

49-
// We store server's address with port (like '127.0.0.1:8081') to be able to build URLs
50-
// (devtoolsFrontendUrl and webSocketDebuggerUrl) for page descriptions. These URLs are used
51-
// by debugger to know where to connect.
52-
_serverBaseUrl: string = '';
53-
5450
_eventReporter: ?EventReporter;
5551

5652
_experiments: Experiments;
@@ -79,14 +75,20 @@ export default class InspectorProxy {
7975
request.url === PAGES_LIST_JSON_URL ||
8076
request.url === PAGES_LIST_JSON_URL_2
8177
) {
78+
const wsPublicBaseUrl = getDevServerUrl(request, 'public', 'ws');
8279
// Build list of pages from all devices.
8380
let result: Array<PageDescription> = [];
8481
Array.from(this._devices.entries()).forEach(([deviceId, device]) => {
8582
result = result.concat(
8683
device
8784
.getPagesList()
8885
.map((page: Page) =>
89-
this._buildPageDescription(deviceId, device, page),
86+
this._buildPageDescription(
87+
deviceId,
88+
device,
89+
page,
90+
wsPublicBaseUrl,
91+
),
9092
),
9193
);
9294
});
@@ -102,11 +104,9 @@ export default class InspectorProxy {
102104
}
103105
}
104106

105-
createWebSocketListeners(devServerBaseUrl: string): {
107+
createWebSocketListeners(): {
106108
[path: string]: WS.Server,
107109
} {
108-
this._serverBaseUrl = devServerBaseUrl;
109-
110110
return {
111111
[WS_DEVICE_URL]: this._createDeviceConnectionWSServer(),
112112
[WS_DEBUGGER_URL]: this._createDebuggerConnectionWSServer(),
@@ -119,16 +119,22 @@ export default class InspectorProxy {
119119
deviceId: string,
120120
device: Device,
121121
page: Page,
122+
wsServerBaseUrl: string,
122123
): PageDescription {
123-
const debuggerUrl = `${this._serverBaseUrl}${WS_DEBUGGER_URL}?device=${deviceId}&page=${page.id}`;
124-
const webSocketDebuggerUrl = 'ws://' + debuggerUrl;
124+
const webSocketDebuggerUrl = `${wsServerBaseUrl}${WS_DEBUGGER_URL}?device=${deviceId}&page=${page.id}`;
125125

126+
const isSecure = webSocketDebuggerUrl.startsWith('wss://');
127+
const webSocketUrlWithoutProtocol = webSocketDebuggerUrl.replace(
128+
/^wss?:\/\//,
129+
'',
130+
);
131+
const scheme = isSecure ? 'wss' : 'ws';
126132
// For now, `/json/list` returns the legacy built-in `devtools://` URL, to
127133
// preserve existing handling by Flipper. This may return a placeholder in
128134
// future -- please use the `/open-debugger` endpoint.
129135
const devtoolsFrontendUrl =
130-
'devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws=' +
131-
encodeURIComponent(webSocketDebuggerUrl);
136+
`devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&${scheme}=` +
137+
encodeURIComponent(webSocketUrlWithoutProtocol);
132138

133139
return {
134140
id: `${deviceId}-${page.id}`,

packages/dev-middleware/src/utils/getDevServerUrl.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,31 @@ export default function getDevServerUrl(
2727
* 'local' for for a URL accessible from the machine running the dev server.
2828
*/
2929
kind: 'public' | 'local',
30+
31+
/**
32+
* If 'ws', returns a WebSocket URL corresponding to the current server,
33+
* with the appropriate scheme (ws or wss) for HTTP / HTTPS connections.
34+
*/
35+
protocolType: 'http' | 'ws' = 'http',
3036
): string {
3137
if (kind === 'public') {
3238
const host = getHost(req);
3339
if (host != null) {
34-
const scheme = getProto(req);
40+
let scheme = getProto(req);
41+
if (protocolType === 'ws') {
42+
scheme = httpSchemeToWsScheme(scheme);
43+
}
3544
return `${scheme}://${host}`;
3645
}
3746
// If we can't determine a public URL, fall back to a local URL, which *might* still work.
3847
}
39-
const scheme =
48+
let scheme =
4049
req.socket instanceof TLSSocket && req.socket.encrypted === true
4150
? 'https'
4251
: 'http';
52+
if (protocolType === 'ws') {
53+
scheme = httpSchemeToWsScheme(scheme);
54+
}
4355
const {localAddress, localPort} = req.socket;
4456
const address =
4557
localAddress && net.isIPv6(localAddress)
@@ -48,3 +60,14 @@ export default function getDevServerUrl(
4860

4961
return `${scheme}://${address}:${localPort}`;
5062
}
63+
64+
function httpSchemeToWsScheme(scheme: string) {
65+
switch (scheme) {
66+
case 'https':
67+
return 'wss';
68+
case 'http':
69+
return 'ws';
70+
default:
71+
throw new Error(`Expected http or https but received ${scheme}`);
72+
}
73+
}

packages/dev-middleware/src/utils/getDevToolsFrontendUrl.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,20 @@ export default function getDevToolsFrontendUrl(
2828
devServerUrl: string,
2929
experiments: Experiments,
3030
): string {
31-
const ws = webSocketDebuggerUrl.replace(/^ws:\/\//, '');
31+
const isSecure = webSocketDebuggerUrl.startsWith('wss://');
32+
const webSocketUrlWithoutProtocol = webSocketDebuggerUrl.replace(
33+
/^wss?:\/\//,
34+
'',
35+
);
36+
const scheme = isSecure ? 'wss' : 'ws';
3237
if (experiments.enableCustomDebuggerFrontend) {
3338
const urlBase = `${devServerUrl}/debugger-frontend/rn_inspector.html`;
34-
return `${urlBase}?ws=${encodeURIComponent(
35-
ws,
39+
return `${urlBase}?${scheme}=${encodeURIComponent(
40+
webSocketUrlWithoutProtocol,
3641
)}&sources.hide_add_folder=true`;
3742
}
3843
const urlBase = `https://chrome-devtools-frontend.appspot.com/serve_rev/@${DEVTOOLS_FRONTEND_REV}/devtools_app.html`;
39-
return `${urlBase}?panel=console&ws=${encodeURIComponent(ws)}`;
44+
return `${urlBase}?panel=console&${scheme}=${encodeURIComponent(
45+
webSocketUrlWithoutProtocol,
46+
)}`;
4047
}

0 commit comments

Comments
 (0)