-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
85 lines (73 loc) · 2.36 KB
/
Copy pathserver.js
File metadata and controls
85 lines (73 loc) · 2.36 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
/**
* Zero-dependency static file server for WebCodexPet.
* Usage: node server.js | npm start
* Open: http://localhost:8765/
*/
const http = require("http");
const fs = require("fs");
const path = require("path");
const ROOT = __dirname;
const PORT = Number(process.env.PORT) || 8765;
const MIME = {
".html": "text/html; charset=utf-8",
".js": "text/javascript; charset=utf-8",
".css": "text/css; charset=utf-8",
".json": "application/json; charset=utf-8",
".webp": "image/webp",
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".svg": "image/svg+xml",
".md": "text/markdown; charset=utf-8",
".txt": "text/plain; charset=utf-8",
".ico": "image/x-icon",
".map": "application/json",
".woff": "font/woff",
".woff2": "font/woff2",
};
function safeJoin(root, urlPath) {
const decoded = decodeURIComponent(urlPath.split("?")[0]);
const joined = path.normalize(path.join(root, decoded));
if (joined !== root && !joined.startsWith(root + path.sep)) return null;
return joined;
}
function send(res, status, body, headers = {}) {
res.writeHead(status, headers);
res.end(body);
}
const server = http.createServer((req, res) => {
if (req.method !== "GET" && req.method !== "HEAD") {
return send(res, 405, "Method Not Allowed");
}
let urlPath = new URL(req.url || "/", `http://localhost:${PORT}`).pathname;
if (urlPath.endsWith("/")) urlPath += "index.html";
const filePath = safeJoin(ROOT, urlPath);
if (!filePath) return send(res, 403, "Forbidden");
fs.stat(filePath, (err, stat) => {
if (err || !stat.isFile()) {
return send(res, 404, "Not Found");
}
const ext = path.extname(filePath).toLowerCase();
const type = MIME[ext] || "application/octet-stream";
const headers = {
"Content-Type": type,
"Content-Length": stat.size,
"Cache-Control": "no-cache",
};
if (req.method === "HEAD") {
return send(res, 200, undefined, headers);
}
const stream = fs.createReadStream(filePath);
res.writeHead(200, headers);
stream.pipe(res);
stream.on("error", () => {
if (!res.headersSent) send(res, 500, "Internal Server Error");
else res.destroy();
});
});
});
server.listen(PORT, () => {
console.log(`WebCodexPet → http://localhost:${PORT}/`);
console.log(`Embed demo → http://localhost:${PORT}/embed/example.html`);
});