-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.js
129 lines (109 loc) · 3.96 KB
/
server.js
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* eslint-disable multiline-ternary */
import chokidar from "chokidar";
import { spawn } from "child_process";
import "colors";
// File utilities
import glob from "glob";
// Server utilities
import express from "express";
import morgan from "morgan";
import http2Express from "http2-express-bridge";
import spdy from "spdy";
import { BLOB, DATA, INLINE, NONE, SELF, expressCspHeader as cspHeaders } from "express-csp-header";
import cors from "cors";
import https from "https";
import http2 from "http2";
import { fileURLToPath } from "url";
import { promises as fs, constants as fsConstants } from "fs";
import path from "path";
async function filePathExists(filePath) {
try {
await fs.access(filePath, fsConstants.F_OK);
return true;
} catch {
return false;
}
}
function logServerMessage(...messages) {
console.log("[SERVER]".blue.bold, ...messages);
}
const url = "https://nkg-msi";
const PORT = process.env.PORT || 3000;
const APP = http2Express(express);
const serverOptions = {
cert: await fs.readFile("./localhost.crt"),
key: await fs.readFile("./localhost.key"),
allowHTTP1: true,
};
APP.use(cspHeaders({
directives: {
"default-src": [BLOB, DATA, SELF],
"script-src": [BLOB, DATA, SELF, INLINE],
"style-src": [BLOB, DATA, SELF, INLINE],
"img-src": ["*"],
"worker-src": [SELF, INLINE, BLOB, DATA],
"block-all-mixed-content": true,
},
}));
APP.use(cors());
APP.use(morgan((tokens, req, res) => {
const method = tokens.method(req, res),
path = tokens.url(req, res),
code = tokens.status(req, res),
length = tokens.res(req, res, "content-length"),
responseTime = tokens["response-time"](req, res);
console.log(req.headers);
logServerMessage(`${ method?.magenta || "<INVALID METHOD>".red.bold } ${
code >= 500 ? code.red.bold
: code >= 400 ? code.yellow.bold
: code >= 300 ? code.cyan.bold
: code >= 200 ? code.green.bold
: 0
} ${ `${ url }${ path }`.blue } in ${ responseTime.magenta.bold }ms${ req.headers.referer ? ` (originated from ${ req.headers.referer.cyan.bold })` : "" }`);
}));
// Favicon
APP.get("/favicon.ico", (_, res) => res.sendFile(path.resolve("./resources/images/favicon.ico")));
// Normal requests
APP.get("*", async({ url, headers }, res, next) => {
const normalizedPath = path.join(path.resolve("."), url);
const absolutePathExists = await filePathExists(normalizedPath);
const resourceType = headers["sec-fetch-dest"];
const isResource = ["style", "script"].includes(resourceType);
const hasExt = path.extname(url);
const stats = absolutePathExists ? await fs.stat(normalizedPath) : null;
if (isResource)
if (absolutePathExists && stats?.isDirectory()) return res.redirect(`${ url }/index.${ resourceType === "style" ? "css" : "js" }`);
if (absolutePathExists && !hasExt) {
if (stats?.isDirectory())
return !url.endsWith("/")
? res.redirect(301, `${ url }/`)
: res.sendFile(path.join(normalizedPath, "index.html"));
} else if (absolutePathExists) return res.sendFile(normalizedPath);
else if (!hasExt && isResource)
return res.redirect(301, `${ url }.${ resourceType === "style" ? "css" : "js" }`);
return next();
});
APP.get("*", (_, res) => res.status(404).sendFile(path.resolve("./404.html")));
APP.use((err, { url, method }, res, next) => {
if (method !== "GET") return res.status(405).sendFile(path.resolve("./405.html"));
try {
decodeURIComponent(url);
} catch (e) {
if (e instanceof URIError) return res.status(400).sendFile(path.resolve("./bad-request.html"));
}
console.log(err);
res.status(500).sendFile(path.resolve("./500.html"));
});
function listen(port, address = "localhost") {
const SERVER = http2.createSecureServer(serverOptions, APP).listen(port, address, () => {
logServerMessage(`listening on port ${ address?.green }:${ port.toString().cyan }`);
});
}
/*
* listen(PORT, "192.168.1.234");
* listen(PORT, "192.168.1.231");
*/
// listen(443, "192.168.1.231");
listen(443, "192.168.1.231");
listen(443, "127.0.0.1");
logServerMessage(`View your server at ${ "https://nkg-msi".green.bold }`);