PRA-only-demo/src/main/fixture/server.ts

70 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { app } from "electron";
import fs from "node:fs";
import http, { type Server } from "node:http";
import path from "node:path";
let server: Server | null = null;
let currentUrl = "";
function fixtureRoot(): string {
const candidates = [
process.resourcesPath ? path.join(process.resourcesPath, "fixture") : "",
path.join(app.getAppPath(), "resources", "fixture"),
path.join(__dirname, "../../resources/fixture")
].filter(Boolean);
const found = candidates.find((candidate) => fs.existsSync(path.join(candidate, "index.html")));
if (!found) throw new Error(`fixture index.html not found; tried ${candidates.join(", ")}`);
return found;
}
export async function startFixtureServer(preferredPort = 17863): Promise<string> {
if (server && currentUrl) return currentUrl;
const root = fixtureRoot();
server = http.createServer((request, response) => {
const url = new URL(request.url || "/", "http://127.0.0.1");
if (url.pathname === "/download.csv") {
response.writeHead(200, { "Content-Type": "text/csv; charset=utf-8", "Content-Disposition": "attachment; filename=orders.csv" });
response.end("name,amount,status\r\nRPA,128,created\r\n");
return;
}
if (url.pathname !== "/" && url.pathname !== "/index.html") {
response.writeHead(404).end("Not found");
return;
}
response.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
fs.createReadStream(path.join(root, "index.html")).pipe(response);
});
const attempts = preferredPort === 0 ? [0] : Array.from({ length: 10 }, (_, index) => preferredPort + index);
for (const port of attempts) {
try {
await new Promise<void>((resolve, reject) => {
const onError = (error: Error) => { server?.removeListener("listening", onListening); reject(error); };
const onListening = () => { server?.removeListener("error", onError); resolve(); };
server!.once("error", onError);
server!.once("listening", onListening);
server!.listen(port, "127.0.0.1");
});
const address = server.address();
const activePort = typeof address === "object" && address ? address.port : port;
currentUrl = `http://127.0.0.1:${activePort}/`;
return currentUrl;
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "EADDRINUSE") throw error;
}
}
throw new Error("无法启动本地演示站:17863-17872 端口均被占用");
}
export async function stopFixtureServer(): Promise<void> {
const active = server;
server = null;
currentUrl = "";
if (!active) return;
await new Promise<void>((resolve) => active.close(() => resolve()));
}
export function fixtureUrl(): string {
return currentUrl;
}