142 lines
5.3 KiB
JavaScript
142 lines
5.3 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.serveStatic = void 0;
|
|
const node_http_1 = __importDefault(require("node:http"));
|
|
const get_port_1 = require("./get-port");
|
|
const offthread_video_server_1 = require("./offthread-video-server");
|
|
const port_config_1 = require("./port-config");
|
|
const serve_handler_1 = require("./serve-handler");
|
|
const serveStatic = async (path, options) => {
|
|
const { listener: offthreadRequest, close: closeCompositor, compositor, } = (0, offthread_video_server_1.startOffthreadVideoServer)({
|
|
downloadMap: options.downloadMap,
|
|
offthreadVideoThreads: options.offthreadVideoThreads,
|
|
logLevel: options.logLevel,
|
|
indent: options.indent,
|
|
offthreadVideoCacheSizeInBytes: options.offthreadVideoCacheSizeInBytes,
|
|
binariesDirectory: options.binariesDirectory,
|
|
});
|
|
const connections = {};
|
|
const server = node_http_1.default.createServer((request, response) => {
|
|
var _a;
|
|
if ((_a = request.url) === null || _a === void 0 ? void 0 : _a.startsWith('/proxy')) {
|
|
return offthreadRequest(request, response);
|
|
}
|
|
if (path === null) {
|
|
response.writeHead(404);
|
|
response.end('Server only supports /proxy');
|
|
return;
|
|
}
|
|
(0, serve_handler_1.serveHandler)(request, response, {
|
|
public: path,
|
|
}).catch(() => {
|
|
if (!response.headersSent) {
|
|
response.writeHead(500);
|
|
}
|
|
response.end('Error serving file');
|
|
});
|
|
});
|
|
server.on('connection', (conn) => {
|
|
let key;
|
|
// Bun 1.0.43 fails on this
|
|
try {
|
|
key = conn.remoteAddress + ':' + conn.remotePort;
|
|
}
|
|
catch (_a) {
|
|
key = ':';
|
|
}
|
|
connections[key] = conn;
|
|
conn.on('close', () => {
|
|
delete connections[key];
|
|
});
|
|
});
|
|
let selectedPort = null;
|
|
const maxTries = 10;
|
|
const portConfig = (0, port_config_1.getPortConfig)(options.forceIPv4);
|
|
for (let i = 0; i < maxTries; i++) {
|
|
let unlock = () => { };
|
|
try {
|
|
selectedPort = await new Promise((resolve, reject) => {
|
|
var _a;
|
|
(0, get_port_1.getDesiredPort)({
|
|
desiredPort: (_a = options === null || options === void 0 ? void 0 : options.port) !== null && _a !== void 0 ? _a : undefined,
|
|
from: 3000,
|
|
to: 3100,
|
|
hostsToTry: portConfig.hostsToTry,
|
|
})
|
|
.then(({ port, unlockPort }) => {
|
|
unlock = unlockPort;
|
|
server.listen({ port, host: portConfig.host });
|
|
server.on('listening', () => {
|
|
resolve(port);
|
|
return unlock();
|
|
});
|
|
server.on('error', (err) => {
|
|
unlock();
|
|
reject(err);
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
unlock();
|
|
return reject(err);
|
|
});
|
|
});
|
|
const destroyConnections = function () {
|
|
for (const key in connections)
|
|
connections[key].destroy();
|
|
};
|
|
const close = async () => {
|
|
await Promise.all([
|
|
new Promise((resolve, reject) => {
|
|
// compositor may have already quit before,
|
|
// this is okay as we are in cleanup phase
|
|
closeCompositor()
|
|
.catch((err) => {
|
|
if (err.message.includes('Compositor quit')) {
|
|
resolve();
|
|
return;
|
|
}
|
|
reject(err);
|
|
})
|
|
.finally(() => {
|
|
resolve();
|
|
});
|
|
}),
|
|
new Promise((resolve, reject) => {
|
|
destroyConnections();
|
|
server.close((err) => {
|
|
if (err) {
|
|
if (err.code ===
|
|
'ERR_SERVER_NOT_RUNNING') {
|
|
return resolve();
|
|
}
|
|
reject(err);
|
|
}
|
|
else {
|
|
resolve();
|
|
}
|
|
});
|
|
}),
|
|
]);
|
|
};
|
|
return { port: selectedPort, close, compositor };
|
|
}
|
|
catch (err) {
|
|
if (!(err instanceof Error)) {
|
|
throw err;
|
|
}
|
|
const codedError = err;
|
|
if (codedError.code === 'EADDRINUSE') {
|
|
// Already in use, try another port
|
|
}
|
|
else {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
throw new Error(`Tried ${maxTries} times to find a free port. Giving up.`);
|
|
};
|
|
exports.serveStatic = serveStatic;
|