This repository was archived by the owner on Jun 12, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev-server.mjs
More file actions
88 lines (74 loc) · 2.77 KB
/
Copy pathdev-server.mjs
File metadata and controls
88 lines (74 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { createReadStream, statSync } from "node:fs";
import { readFile } from "node:fs/promises";
import { createServer } from "node:http";
import { extname, join, normalize } from "node:path";
import { fileURLToPath } from "node:url";
import { onRequestGet as download } from "./functions/__down.js";
import { onRequestPost as upload } from "./functions/__up.js";
import { onRequestGet as trace } from "./functions/api/trace.js";
const root = fileURLToPath(new URL("./public", import.meta.url));
const port = Number(process.env.PORT || 4173);
createServer(async (incoming, outgoing) => {
const url = new URL(incoming.url || "/", `http://${incoming.headers.host}`);
if (url.pathname === "/__down" && incoming.method === "GET") {
return sendWebResponse(outgoing, download({ request: toRequest(incoming, url) }));
}
if (url.pathname === "/__up" && incoming.method === "POST") {
return sendWebResponse(outgoing, await upload({ request: toRequest(incoming, url) }));
}
if (url.pathname === "/api/trace" && incoming.method === "GET") {
return sendWebResponse(outgoing, trace({ request: toRequest(incoming, url) }));
}
return serveStatic(url.pathname, outgoing);
}).listen(port, "127.0.0.1", () => {
console.log(`Speed Test local server: http://127.0.0.1:${port}`);
});
function toRequest(incoming, url) {
const init = {
method: incoming.method,
headers: incoming.headers,
};
if (incoming.method !== "GET" && incoming.method !== "HEAD") {
init.body = incoming;
init.duplex = "half";
}
return new Request(url, init);
}
async function sendWebResponse(outgoing, response) {
outgoing.writeHead(response.status, Object.fromEntries(response.headers));
if (!response.body) {
outgoing.end();
return;
}
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
outgoing.write(value);
}
outgoing.end();
}
async function serveStatic(pathname, outgoing) {
const requested = pathname === "/" ? "/index.html" : pathname;
const safePath = normalize(requested).replace(/^(\.\.[/\\])+/, "");
const filePath = join(root, safePath);
try {
const stats = statSync(filePath);
if (!stats.isFile()) throw new Error("Not a file");
outgoing.writeHead(200, { "Content-Type": contentType(extname(filePath)) });
createReadStream(filePath).pipe(outgoing);
} catch {
const fallback = await readFile(join(root, "index.html"));
outgoing.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
outgoing.end(fallback);
}
}
function contentType(extension) {
return (
{
".html": "text/html; charset=utf-8",
".css": "text/css; charset=utf-8",
".js": "text/javascript; charset=utf-8",
}[extension] || "application/octet-stream"
);
}