1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-09 16:21:51 +00:00

Handle directories in mod protocol handler (#87)

* Handle directories in mod protocol handler
Previously we would return an error about a file not existing, which kinda makes sense, considering a directory isn't a file.
Now with this commit, if the url resolve to a directory, it will return a json array with the relative paths of the file in that directory.

* Make directory index work with ASAR archives

Also fix directory index having higher priority than normal requests and
simplify URL handling.

---------

Co-authored-by: Даниїл Григор'єв <dengr1065@gmail.com>
This commit is contained in:
cody-ferguson 2025-07-01 13:30:55 -04:00 committed by GitHub
parent ba2e74b993
commit 0167b9d6a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,4 +1,5 @@
import { net, protocol } from "electron";
import { lstat, readdir } from "node:fs/promises";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { ModLoader } from "./loader.js";
@ -31,20 +32,50 @@ export class ModProtocolHandler {
}
private async handler(request: GlobalRequest): Promise<GlobalResponse> {
const fileUrl = this.getFileUrlForRequest(request);
if (fileUrl === undefined) {
return Response.error();
}
try {
const fileUrl = this.getFileUrlForRequest(request);
if (fileUrl === undefined) {
return Response.error();
return await net.fetch(fileUrl.toString());
} catch (err) {
// Check if this is a directory request
const directoryIndex = await this.getDirectoryIndex(fileUrl);
if (directoryIndex !== null) {
return directoryIndex;
}
return await net.fetch(fileUrl);
} catch (err) {
console.error("Failed to fetch:", err);
return Response.error();
}
}
private getFileUrlForRequest(request: GlobalRequest): string | undefined {
private async getDirectoryIndex(fileUrl: URL): Promise<GlobalResponse | null> {
if (!fileUrl.pathname.endsWith("/")) {
return null;
}
// Remove the trailing slash
fileUrl.pathname = fileUrl.pathname.slice(0, -1);
try {
const stats = await lstat(fileUrl);
if (!stats.isDirectory()) {
return null;
}
const dir = await readdir(fileUrl, { withFileTypes: true });
const result = dir.map(entry => entry.name + (entry.isDirectory() ? "/" : ""));
return Response.json(result);
} catch (err) {
console.error("Failed to get directory index:", err);
return null;
}
}
private getFileUrlForRequest(request: GlobalRequest): URL | undefined {
// mod://mod-id/path/to/file
const modUrl = new URL(request.url);
const mod = this.modLoader.getModById(modUrl.hostname);
@ -58,10 +89,10 @@ export class ModProtocolHandler {
// Check if the path escapes the bundle as per Electron example
// NOTE: this means file names cannot start with ..
const relative = path.relative(bundle, filePath);
if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative)) {
if (relative.startsWith("..") || path.isAbsolute(relative)) {
return undefined;
}
return pathToFileURL(filePath).toString();
return pathToFileURL(filePath);
}
}