diff --git a/desktop/flipper-server/package.json b/desktop/flipper-server/package.json index 0cf31e80a..a8e6d4a28 100644 --- a/desktop/flipper-server/package.json +++ b/desktop/flipper-server/package.json @@ -10,12 +10,15 @@ "bugs": "https://github.com/facebook/flipper/issues", "dependenciesComment": "mac-ca is required dynamically for darwin, node-fetch is treated special in electron-requires, not sure why", "dependencies": { + "http-proxy": "^1.18.1", "mac-ca": "^1.0.6", "node-fetch": "^2.6.7", - "ws": "^8.5.0" + "ws": "^8.5.0", + "xdg-basedir": "^4" }, "devDependencies": { "@types/express": "^4.17.13", + "@types/http-proxy": "^1.17.8", "@types/node": "^15.12.5", "chalk": "^4.1.2", "express": "^4.17.3", diff --git a/desktop/flipper-server/src/startBaseServer.tsx b/desktop/flipper-server/src/startBaseServer.tsx index 1f115d06e..3101a8b9c 100644 --- a/desktop/flipper-server/src/startBaseServer.tsx +++ b/desktop/flipper-server/src/startBaseServer.tsx @@ -7,6 +7,7 @@ * @format */ +import os from 'os'; import express, {Express} from 'express'; import http from 'http'; import path from 'path'; @@ -14,6 +15,10 @@ import fs from 'fs-extra'; import {VerifyClientCallbackSync, WebSocketServer} from 'ws'; import {WEBSOCKET_MAX_MESSAGE_SIZE} from 'flipper-server-core'; import {parse} from 'url'; +import xdgBasedir from 'xdg-basedir'; +import proxy from 'http-proxy'; + +import {userInfo} from 'os'; type Config = { port: number; @@ -26,7 +31,7 @@ export async function startBaseServer(config: Config): Promise<{ server: http.Server; socket: WebSocketServer; }> { - const {app, server} = await startAssetServer(config); + const {app, server} = await startHTTPServer(config); const socket = addWebsocket(server, config); return { app, @@ -35,7 +40,7 @@ export async function startBaseServer(config: Config): Promise<{ }; } -function startAssetServer( +async function startHTTPServer( config: Config, ): Promise<{app: Express; server: http.Server}> { const app = express(); @@ -59,10 +64,41 @@ function startAssetServer( app.use(express.static(config.staticDir)); + return startProxyServer(config, app); +} + +async function startProxyServer( + config: Config, + app: Express, +): Promise<{app: Express; server: http.Server}> { const server = http.createServer(app); + // For now, we only support domain socket access on POSIX-like systems. + if (os.platform() === 'win32') { + return new Promise((resolve) => { + console.log(`Starting server on http://localhost:${config.port}`); + server.listen(config.port, undefined, () => resolve({app, server})); + }); + } + + const runtimeDir = xdgBasedir.runtime || '/tmp'; + await fs.mkdirp(runtimeDir); + const socketPath = `${runtimeDir}/flipper-server-${userInfo().uid}.sock`; + + // TODO: More careful cleanup. + await fs.rm(socketPath, {force: true}); + + const proxyServer = proxy.createProxyServer({ + target: {host: 'localhost', port: 0, socketPath}, + autoRewrite: true, + ws: true, + }); + console.log('Starting socket server on ', socketPath); + console.log(`Starting proxy server on http://localhost:${config.port}`); + return new Promise((resolve) => { - server.listen(config.port, undefined, () => resolve({app, server})); + proxyServer.listen(config.port); + server.listen(socketPath, undefined, () => resolve({app, server})); }); } diff --git a/desktop/flipper-server/src/startSocketServer.tsx b/desktop/flipper-server/src/startSocketServer.tsx index 6cd2a102c..9d18fd144 100644 --- a/desktop/flipper-server/src/startSocketServer.tsx +++ b/desktop/flipper-server/src/startSocketServer.tsx @@ -23,9 +23,12 @@ export function startSocketServer( socket: WebSocketServer, ) { socket.on('connection', (client, req) => { - const clientAddress = `${req.socket.remoteAddress}:${req.socket.remotePort}`; + const clientAddress = + (req.socket.remoteAddress && + ` ${req.socket.remoteAddress}:${req.socket.remotePort}`) || + ''; - console.log(chalk.green(`Client connected ${clientAddress}`)); + console.log(chalk.green(`Client connected${clientAddress}`)); let connected = true; diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 8b428eedf..b9e8a79b2 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -2504,6 +2504,13 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/http-proxy@^1.17.8": + version "1.17.8" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" + integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== + dependencies: + "@types/node" "*" + "@types/inquirer@^7.3.3": version "7.3.3" resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-7.3.3.tgz#92e6676efb67fa6925c69a2ee638f67a822952ac" @@ -5925,7 +5932,7 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -eventemitter3@^4.0.7: +eventemitter3@^4.0.0, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -6351,6 +6358,11 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" +follow-redirects@^1.0.0: + version "1.14.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" + integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== + follow-redirects@^1.14.8: version "1.14.8" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" @@ -6882,6 +6894,15 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -10806,6 +10827,11 @@ requireindex@~1.1.0: resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162" integrity sha1-5UBLgVV+91225JxacgBIk/4D4WI= +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + reselect@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.5.tgz#852c361247198da6756d07d9296c2b51eddb79f6" @@ -12637,7 +12663,7 @@ ws@~8.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== -xdg-basedir@^4.0.0: +xdg-basedir@^4, xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==