Summary: Make sure the flipper server socket only accepts local connections Reviewed By: aigoncharov Differential Revision: D33020251 fbshipit-source-id: 53e95e4871a45f3a3fa14f999499568a5a6b4995
82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import express, {Express} from 'express';
|
|
import http from 'http';
|
|
import path from 'path';
|
|
import fs from 'fs-extra';
|
|
import socketio from 'socket.io';
|
|
import {WEBSOCKET_MAX_MESSAGE_SIZE} from 'flipper-server-core';
|
|
|
|
type Config = {
|
|
port: number;
|
|
staticDir: string;
|
|
entry: string;
|
|
};
|
|
|
|
export async function startBaseServer(config: Config): Promise<{
|
|
app: Express;
|
|
server: http.Server;
|
|
socket: socketio.Server;
|
|
}> {
|
|
const {app, server} = await startAssetServer(config);
|
|
const socket = addWebsocket(server, config);
|
|
return {
|
|
app,
|
|
server,
|
|
socket,
|
|
};
|
|
}
|
|
|
|
function startAssetServer(
|
|
config: Config,
|
|
): Promise<{app: Express; server: http.Server}> {
|
|
const app = express();
|
|
|
|
app.use((_req, res, next) => {
|
|
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
|
res.header('Expires', '-1');
|
|
res.header('Pragma', 'no-cache');
|
|
next();
|
|
});
|
|
|
|
app.get('/', (_req, res) => {
|
|
fs.readFile(path.join(config.staticDir, config.entry), (_err, content) => {
|
|
res.end(content);
|
|
});
|
|
});
|
|
|
|
app.use(express.static(config.staticDir));
|
|
|
|
const server = http.createServer(app);
|
|
|
|
return new Promise((resolve) => {
|
|
server.listen(config.port, 'localhost', () => resolve({app, server}));
|
|
});
|
|
}
|
|
|
|
function addWebsocket(server: http.Server, config: Config) {
|
|
const validHost = `localhost:${config.port}`;
|
|
const io = new socketio.Server(server, {
|
|
maxHttpBufferSize: WEBSOCKET_MAX_MESSAGE_SIZE,
|
|
allowRequest(req, callback) {
|
|
const noOriginHeader = req.headers.origin === undefined;
|
|
if (noOriginHeader && req.headers.host === validHost) {
|
|
callback(null, true);
|
|
} else {
|
|
console.warn(
|
|
`Refused sockect connection from cross domain request, origin: ${req.headers.origin}, host: ${req.headers.host}. Expected: ${validHost}`,
|
|
);
|
|
callback(null, false);
|
|
}
|
|
},
|
|
});
|
|
return io;
|
|
}
|