Skip to content

Commit cdfd217

Browse files
committed
fix: Attempt again
1 parent 49b4338 commit cdfd217

File tree

2 files changed

+71
-61
lines changed

2 files changed

+71
-61
lines changed

src/back/index.ts

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,12 +1317,12 @@ async function onRemoveCurationFile(folder: string, relativePath: string) {
13171317
}
13181318
}
13191319

1320-
function onFileServerRequestExtData(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): void {
1320+
async function onFileServerRequestExtData(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
13211321
// Split URL section into parts (/extdata/<extId>/<relativePath>)
13221322
const splitPath = pathname.split('/');
13231323
const extId = splitPath.length > 0 ? splitPath[0] : '';
13241324
const relativePath = splitPath.length > 1 ? splitPath.slice(1).join('/') : '';
1325-
state.extensionsService.getExtension(extId)
1325+
return state.extensionsService.getExtension(extId)
13261326
.then(ext => {
13271327
if (ext) {
13281328
// Only serve from <extPath>/static/
@@ -1348,8 +1348,8 @@ function onFileServerRequestExtData(pathname: string, url: URL, req: http.Incomi
13481348
});
13491349
}
13501350

1351-
function onFileServerRequestExtIcons(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): void {
1352-
state.extensionsService.getExtension(pathname)
1351+
async function onFileServerRequestExtIcons(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
1352+
return state.extensionsService.getExtension(pathname)
13531353
.then((ext) => {
13541354
if (ext && ext.manifest.icon) {
13551355
const filePath = path.join(ext.extensionPath, ext.manifest.icon);
@@ -1364,7 +1364,7 @@ function onFileServerRequestExtIcons(pathname: string, url: URL, req: http.Incom
13641364
});
13651365
}
13661366

1367-
function onFileServerRequestThemes(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): void {
1367+
async function onFileServerRequestThemes(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
13681368
const splitPath = pathname.split('/');
13691369
// Find theme associated with the path (/Theme/<themeId>/<relativePath>)
13701370
const themeId = splitPath.length > 0 ? splitPath[0] : '';
@@ -1396,8 +1396,12 @@ async function onFileServerRequestRuffle(pathname: string, url: URL, req: http.I
13961396
res.end();
13971397
}
13981398
});
1399-
fs.stat(filePath)
1400-
.then((stats) => {
1399+
const stats = await fs.promises.stat(filePath)
1400+
.catch(() => {
1401+
res.writeHead(404);
1402+
res.end();
1403+
});
1404+
if (stats) {
14011405
// Respond with file
14021406
res.writeHead(200, {
14031407
'Content-Type': mime.getType(path.extname(filePath)) || '',
@@ -1414,12 +1418,10 @@ async function onFileServerRequestRuffle(pathname: string, url: URL, req: http.I
14141418
} else {
14151419
res.end();
14161420
}
1417-
})
1418-
.catch(async () => {
1419-
// Can't read file
1421+
} else {
14201422
res.writeHead(404);
14211423
res.end();
1422-
});
1424+
}
14231425
} else {
14241426
res.writeHead(404);
14251427
res.end();
@@ -1455,8 +1457,10 @@ async function onFileServerRequestImages(pathname: string, url: URL, req: http.I
14551457
});
14561458
return;
14571459
}
1458-
res.writeHead(400);
1459-
res.end();
1460+
if (!res.writableEnded) {
1461+
res.writeHead(400);
1462+
res.end();
1463+
}
14601464
} else if (req.method === 'GET' || req.method === 'HEAD') {
14611465
req.on('error', (err) => {
14621466
log.error('Launcher', `Error serving Game image - ${err}`);
@@ -1524,51 +1528,51 @@ async function onFileServerRequestImages(pathname: string, url: URL, req: http.I
15241528
}
15251529
});
15261530
} else {
1527-
res.writeHead(404);
1528-
res.end();
1531+
if (!res.writableEnded) {
1532+
res.writeHead(404);
1533+
res.end();
1534+
}
15291535
}
15301536
}
15311537
}
15321538

1533-
function onFileServerRequestLogos(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): void {
1539+
async function onFileServerRequestLogos(pathname: string, url: URL, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
15341540
const logoSet = state.registry.logoSets.get(state.preferences.currentLogoSet || '');
15351541
const logoFolder = logoSet && logoSet.files.includes(pathname)
15361542
? logoSet.fullPath
15371543
: path.join(state.config.flashpointPath, state.preferences.logoFolderPath);
15381544
const filePath = path.join(logoFolder, pathname);
15391545
if (filePath.startsWith(logoFolder)) {
1540-
fs.access(filePath, fs.constants.F_OK, async (err) => {
1541-
if (err) {
1542-
// Maybe we're on a case sensitive platform?
1543-
try {
1544-
const folder = path.dirname(filePath);
1545-
const filename = path.basename(filePath);
1546-
if (filePath.startsWith(logoFolder)) {
1547-
const files = await fs.readdir(folder);
1548-
for (const file of files) {
1549-
if (file.toLowerCase() == filename.toLowerCase()) {
1550-
serveFile(req, res, path.join(folder, file));
1551-
return;
1552-
}
1546+
try {
1547+
await fs.promises.access(filePath, fs.constants.F_OK);
1548+
serveFile(req, res, filePath);
1549+
} catch (err) {
1550+
// Maybe we're on a case sensitive platform?
1551+
try {
1552+
const folder = path.dirname(filePath);
1553+
const filename = path.basename(filePath);
1554+
if (filePath.startsWith(logoFolder)) {
1555+
const files = await fs.readdir(folder);
1556+
for (const file of files) {
1557+
if (file.toLowerCase() == filename.toLowerCase()) {
1558+
serveFile(req, res, path.join(folder, file));
1559+
return;
15531560
}
15541561
}
1555-
} catch { /** Let error drop to return default image instead */ }
1556-
// File doesn't exist, serve default image
1557-
const basePath = (!state.isDev && state.isElectron) ? path.join(path.dirname(state.exePath), 'resources/app.asar/build') : path.join(process.cwd(), 'build');
1558-
const replacementFilePath = path.join(basePath, 'window/images/Logos', pathname);
1559-
if (replacementFilePath.startsWith(basePath)) {
1560-
fs.access(replacementFilePath, fs.constants.F_OK, (err) => {
1561-
if (err) {
1562-
serveFile(req, res, path.join(basePath, DEFAULT_LOGO_PATH));
1563-
} else {
1564-
serveFile(req, res, replacementFilePath);
1565-
}
1566-
});
15671562
}
1568-
} else {
1569-
serveFile(req, res, filePath);
1563+
} catch { /** Let error drop to return default image instead */ }
1564+
// File doesn't exist, serve default image
1565+
const basePath = (!state.isDev && state.isElectron) ? path.join(path.dirname(state.exePath), 'resources/app.asar/build') : path.join(process.cwd(), 'build');
1566+
const replacementFilePath = path.join(basePath, 'window/images/Logos', pathname);
1567+
if (replacementFilePath.startsWith(basePath)) {
1568+
try {
1569+
await fs.promises.access(replacementFilePath, fs.constants.F_OK);
1570+
serveFile(req, res, replacementFilePath);
1571+
} catch (err) {
1572+
serveFile(req, res, path.join(basePath, DEFAULT_LOGO_PATH));
1573+
}
15701574
}
1571-
});
1575+
}
15721576
}
15731577
}
15741578

src/back/util/FileServer.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,34 @@ export function serveFile(req: http.IncomingMessage, res: http.ServerResponse, f
8787
});
8888
fs.stat(filePath, (error, stats) => {
8989
if (error || stats && !stats.isFile()) {
90-
res.writeHead(404);
91-
res.end();
90+
if (!res.writableEnded && !res.destroyed) {
91+
res.writeHead(404);
92+
res.end();
93+
}
9294
} else {
93-
res.writeHead(200, {
94-
'Content-Type': mime.getType(path.extname(filePath)) || '',
95-
'Content-Length': stats.size,
96-
});
97-
if (req.method === 'GET') {
98-
const stream = fs.createReadStream(filePath);
99-
stream.on('error', error => {
100-
console.warn(`File server failed to stream file. ${error}`);
101-
stream.destroy(); // Calling "destroy" inside the "error" event seems like it could case an endless loop (although it hasn't thus far)
102-
if (!res.writableEnded) { res.end(); }
95+
if (!res.writableEnded && !res.destroyed) {
96+
res.writeHead(200, {
97+
'Content-Type': mime.getType(path.extname(filePath)) || '',
98+
'Content-Length': stats.size,
10399
});
104-
stream.pipe(res);
105-
} else {
106-
res.end();
100+
if (req.method === 'GET') {
101+
const stream = fs.createReadStream(filePath);
102+
stream.on('error', error => {
103+
console.warn(`File server failed to stream file. ${error}`);
104+
stream.destroy(); // Calling "destroy" inside the "error" event seems like it could case an endless loop (although it hasn't thus far)
105+
if (!res.writableEnded) { res.end(); }
106+
});
107+
stream.pipe(res);
108+
} else {
109+
res.end();
110+
}
107111
}
108112
}
109113
});
110114
} else {
111-
res.writeHead(404);
112-
res.end();
115+
if (!res.writableEnded && !res.destroyed) {
116+
res.writeHead(404);
117+
res.end();
118+
}
113119
}
114120
}

0 commit comments

Comments
 (0)