devtunnel-cli 3.0.16 → 3.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/proxy-server.js +8 -1
- package/src/core/start.js +602 -573
- package/src/core/static-server.js +87 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal static file server for HTML projects.
|
|
3
|
+
* Used only when devtunnel detects an HTML project and no server is running.
|
|
4
|
+
* Usage: node static-server.js <directory> <port>
|
|
5
|
+
*/
|
|
6
|
+
import http from "http";
|
|
7
|
+
import fs from "fs";
|
|
8
|
+
import path from "path";
|
|
9
|
+
const ROOT = path.resolve(process.argv[2] || ".");
|
|
10
|
+
const PORT = parseInt(process.argv[3] || "8080", 10);
|
|
11
|
+
|
|
12
|
+
const MIME = {
|
|
13
|
+
".html": "text/html",
|
|
14
|
+
".htm": "text/html",
|
|
15
|
+
".css": "text/css",
|
|
16
|
+
".js": "application/javascript",
|
|
17
|
+
".json": "application/json",
|
|
18
|
+
".png": "image/png",
|
|
19
|
+
".jpg": "image/jpeg",
|
|
20
|
+
".jpeg": "image/jpeg",
|
|
21
|
+
".gif": "image/gif",
|
|
22
|
+
".ico": "image/x-icon",
|
|
23
|
+
".svg": "image/svg+xml",
|
|
24
|
+
".webp": "image/webp",
|
|
25
|
+
".woff": "font/woff",
|
|
26
|
+
".woff2": "font/woff2",
|
|
27
|
+
".ttf": "font/ttf",
|
|
28
|
+
".txt": "text/plain",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const server = http.createServer((req, res) => {
|
|
32
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
33
|
+
res.writeHead(405, { "Content-Type": "text/plain" });
|
|
34
|
+
res.end("Method Not Allowed");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let p = path.join(ROOT, path.normalize(req.url).replace(/^\//, "") || ".");
|
|
38
|
+
if (!path.isAbsolute(p)) p = path.join(ROOT, p);
|
|
39
|
+
if (!p.startsWith(ROOT)) {
|
|
40
|
+
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
41
|
+
res.end("Forbidden");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
fs.stat(p, (err, stat) => {
|
|
45
|
+
if (err) {
|
|
46
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
47
|
+
res.end("Not Found");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (stat.isDirectory()) {
|
|
51
|
+
p = path.join(p, "index.html");
|
|
52
|
+
return fs.stat(p, (e2, s2) => {
|
|
53
|
+
if (e2 || !s2.isFile()) {
|
|
54
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
55
|
+
res.end("Not Found");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
serveFile(p, s2, req, res);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
serveFile(p, stat, req, res);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
function serveFile(filePath, stat, req, res) {
|
|
66
|
+
const ext = path.extname(filePath);
|
|
67
|
+
const contentType = MIME[ext] || "application/octet-stream";
|
|
68
|
+
res.setHeader("Content-Type", contentType);
|
|
69
|
+
res.setHeader("Content-Length", stat.size);
|
|
70
|
+
if (req.method === "HEAD") {
|
|
71
|
+
res.end();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const stream = fs.createReadStream(filePath);
|
|
75
|
+
stream.on("error", () => {
|
|
76
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
77
|
+
res.end("Internal Server Error");
|
|
78
|
+
});
|
|
79
|
+
stream.pipe(res);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
server.listen(PORT, "127.0.0.1", () => {
|
|
83
|
+
// Server ready; no console output to avoid cluttering devtunnel output
|
|
84
|
+
});
|
|
85
|
+
server.on("error", (err) => {
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|