minimalistic-server 0.0.53 → 0.0.55
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/index.mjs +131 -62
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -36,6 +36,70 @@ function safePrint(data, isError = false) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
const escapeHtmlMap = {
|
|
40
|
+
"&": "&",
|
|
41
|
+
"<": "<",
|
|
42
|
+
">": ">",
|
|
43
|
+
'"': """,
|
|
44
|
+
"'": "'",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const unescapeHtmlMap = {
|
|
48
|
+
" ": "\u00A0",
|
|
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
|
+
|
|
39
103
|
const mimeTypes = {
|
|
40
104
|
"123": "application/vnd.lotus-1-2-3",
|
|
41
105
|
"3dml": "text/vnd.in3d.3dml",
|
|
@@ -2105,22 +2169,13 @@ export function serve(routes, port = 80, staticFileDirectoryOrDirectories = null
|
|
|
2105
2169
|
|
|
2106
2170
|
}
|
|
2107
2171
|
|
|
2108
|
-
export function escapeHtml(
|
|
2109
|
-
return
|
|
2110
|
-
.replace(/&/gm, "&")
|
|
2111
|
-
.replace(/</gm, "<")
|
|
2112
|
-
.replace(/>/gm, ">")
|
|
2113
|
-
.replace(/"/gm, """)
|
|
2114
|
-
.replace(/'/gm, "'") ?? '';
|
|
2172
|
+
export function escapeHtml(str) {
|
|
2173
|
+
return str?.toString().replace(/[&<>"']/gm, (c) => escapeHtmlMap[c]) ?? '';
|
|
2115
2174
|
}
|
|
2116
2175
|
|
|
2117
2176
|
export function unescapeHtml(htmlStr) {
|
|
2118
2177
|
return htmlStr?.toString()
|
|
2119
|
-
.replace(/&
|
|
2120
|
-
.replace(/</gm, "<")
|
|
2121
|
-
.replace(/>/gm, ">")
|
|
2122
|
-
.replace(/"/gm, '"')
|
|
2123
|
-
.replace(/'/gm, "'") ?? '';
|
|
2178
|
+
.replace(/&(?:#(\d+|x[\dA-Fa-f]+)|([^;]+));/gm, (entity, digits, entityName) => unescapeHtmlMap[entity] ?? entityName ?? String.fromCharCode("0" + digits));
|
|
2124
2179
|
}
|
|
2125
2180
|
|
|
2126
2181
|
export function unserve(port = 80) {
|
|
@@ -2133,6 +2188,59 @@ export function unserve(port = 80) {
|
|
|
2133
2188
|
servers.delete(port);
|
|
2134
2189
|
}
|
|
2135
2190
|
|
|
2191
|
+
function wrapInMiddlewares(callback, preMiddlewares = [], postMiddlewares = [], handleServerError = null) {
|
|
2192
|
+
let resultCallback = async (request, handleOptions = false) => {
|
|
2193
|
+
let response;
|
|
2194
|
+
|
|
2195
|
+
try {
|
|
2196
|
+
for (const pre of preMiddlewares) {
|
|
2197
|
+
const req = await pre(request);
|
|
2198
|
+
|
|
2199
|
+
if (req instanceof Request) {
|
|
2200
|
+
request = req;
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
response = wrapInResponseClass(handleOptions ? new CustomResponse(Buffer.from(''), 200, { 'Content-Type': null }) : await callback(request));
|
|
2205
|
+
} catch (error) {
|
|
2206
|
+
if (error instanceof Response) {
|
|
2207
|
+
response = error;
|
|
2208
|
+
} else {
|
|
2209
|
+
throw error;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
for (const post of postMiddlewares) {
|
|
2214
|
+
const res = await post(request, response);
|
|
2215
|
+
|
|
2216
|
+
if (res !== undefined) {
|
|
2217
|
+
response = wrapInResponseClass(res);
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
return response;
|
|
2222
|
+
};
|
|
2223
|
+
|
|
2224
|
+
if (handleServerError) {
|
|
2225
|
+
const tempCallback = resultCallback;
|
|
2226
|
+
|
|
2227
|
+
resultCallback = async (request, handleOptions = false) => {
|
|
2228
|
+
try {
|
|
2229
|
+
return await tempCallback(request, handleOptions);
|
|
2230
|
+
} catch (error) {
|
|
2231
|
+
if (error instanceof Response) {
|
|
2232
|
+
throw error;
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
safePrint(error);
|
|
2236
|
+
return wrapInResponseClass(await handleServerError(request, error));
|
|
2237
|
+
}
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
return resultCallback;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2136
2244
|
function normalizeStaticFileDirectories(staticFileDirectoryOrDirectories) {
|
|
2137
2245
|
if (staticFileDirectoryOrDirectories !== null && staticFileDirectoryOrDirectories !== undefined) {
|
|
2138
2246
|
if (!Array.isArray(staticFileDirectoryOrDirectories)) {
|
|
@@ -2140,27 +2248,33 @@ function normalizeStaticFileDirectories(staticFileDirectoryOrDirectories) {
|
|
|
2140
2248
|
}
|
|
2141
2249
|
|
|
2142
2250
|
staticFileDirectoryOrDirectories = staticFileDirectoryOrDirectories.filter(x => x !== null && typeof x === 'object' || typeof x === 'string').map(x => {
|
|
2143
|
-
let serverFilePath = '', urlPath = '', showWholeDirectory = false, maxAgeInSeconds = -1;
|
|
2251
|
+
let serverFilePath = '', urlPath = '', showWholeDirectory = false, maxAgeInSeconds = -1, preMiddlewares = [], postMiddlewares = [];
|
|
2144
2252
|
const defaultMaxAge = 5 * 24 * 60 * 60;
|
|
2145
2253
|
|
|
2146
2254
|
if (typeof x === 'string') {
|
|
2147
2255
|
serverFilePath = urlPath = x;
|
|
2148
2256
|
showWholeDirectory = false;
|
|
2149
2257
|
maxAgeInSeconds = defaultMaxAge;
|
|
2258
|
+
preMiddlewares = [];
|
|
2259
|
+
postMiddlewares = [];
|
|
2150
2260
|
} else {
|
|
2151
|
-
({ serverFilePath, urlPath, showWholeDirectory, maxAgeInSeconds } = x);
|
|
2261
|
+
({ serverFilePath, urlPath, showWholeDirectory, maxAgeInSeconds, preMiddlewares, postMiddlewares } = x);
|
|
2152
2262
|
}
|
|
2153
2263
|
|
|
2154
2264
|
urlPath = `${urlPath}`.split('/').filter(x => x).join('/');
|
|
2155
2265
|
serverFilePath = `${serverFilePath}`.split('/').filter(x => x).join('/');
|
|
2156
2266
|
showWholeDirectory = !!showWholeDirectory;
|
|
2157
2267
|
maxAgeInSeconds = Math.floor(+(maxAgeInSeconds ?? defaultMaxAge));
|
|
2268
|
+
preMiddlewares = Array.isArray(preMiddlewares) ? preMiddlewares.filter(x => typeof x === 'function') : [];
|
|
2269
|
+
postMiddlewares = Array.isArray(postMiddlewares) ? postMiddlewares.filter(x => typeof x === 'function') : [];
|
|
2158
2270
|
|
|
2159
2271
|
return {
|
|
2160
2272
|
urlPath,
|
|
2161
2273
|
serverFilePath,
|
|
2162
2274
|
showWholeDirectory,
|
|
2163
2275
|
maxAgeInSeconds,
|
|
2276
|
+
preMiddlewares,
|
|
2277
|
+
postMiddlewares,
|
|
2164
2278
|
};
|
|
2165
2279
|
});
|
|
2166
2280
|
} else {
|
|
@@ -2192,54 +2306,7 @@ function normalizeRoutes(routes, handleServerError) {
|
|
|
2192
2306
|
flattenRecursively(root[prop], newPath, preMiddlewares, postMiddlewares);
|
|
2193
2307
|
}
|
|
2194
2308
|
} else if (typeof root === 'function') {
|
|
2195
|
-
flatten[path] =
|
|
2196
|
-
let response;
|
|
2197
|
-
|
|
2198
|
-
try {
|
|
2199
|
-
for (const pre of preMiddlewares) {
|
|
2200
|
-
const req = await pre(request);
|
|
2201
|
-
|
|
2202
|
-
if (req instanceof Request) {
|
|
2203
|
-
request = req;
|
|
2204
|
-
}
|
|
2205
|
-
}
|
|
2206
|
-
|
|
2207
|
-
response = wrapInResponseClass(handleOptions ? new CustomResponse(Buffer.from(''), 200, { 'Content-Type': null }) : await root(request));
|
|
2208
|
-
} catch (error) {
|
|
2209
|
-
if (error instanceof Response) {
|
|
2210
|
-
response = error;
|
|
2211
|
-
} else {
|
|
2212
|
-
throw error;
|
|
2213
|
-
}
|
|
2214
|
-
}
|
|
2215
|
-
|
|
2216
|
-
for (const post of postMiddlewares) {
|
|
2217
|
-
const res = await post(request, response);
|
|
2218
|
-
|
|
2219
|
-
if (res !== undefined) {
|
|
2220
|
-
response = wrapInResponseClass(res);
|
|
2221
|
-
}
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
|
-
return response;
|
|
2225
|
-
};
|
|
2226
|
-
|
|
2227
|
-
if (handleServerError) {
|
|
2228
|
-
const callback = flatten[path];
|
|
2229
|
-
|
|
2230
|
-
flatten[path] = async (request, handleOptions = false) => {
|
|
2231
|
-
try {
|
|
2232
|
-
return await callback(request, handleOptions);
|
|
2233
|
-
} catch (error) {
|
|
2234
|
-
if (error instanceof Response) {
|
|
2235
|
-
throw error;
|
|
2236
|
-
}
|
|
2237
|
-
|
|
2238
|
-
safePrint(error);
|
|
2239
|
-
return wrapInResponseClass(await handleServerError(request, error));
|
|
2240
|
-
}
|
|
2241
|
-
};
|
|
2242
|
-
}
|
|
2309
|
+
flatten[path] = wrapInMiddlewares(root, preMiddlewares, postMiddlewares, handleServerError);
|
|
2243
2310
|
}
|
|
2244
2311
|
}
|
|
2245
2312
|
|
|
@@ -2378,6 +2445,8 @@ async function handleRequest(req, routes, staticFileDirectories, handleNotFoundE
|
|
|
2378
2445
|
|
|
2379
2446
|
return resp;
|
|
2380
2447
|
};
|
|
2448
|
+
|
|
2449
|
+
routeHandler = wrapInMiddlewares(routeHandler, staticFileOrDirectory.preMiddlewares, staticFileOrDirectory.postMiddlewares);
|
|
2381
2450
|
} else {
|
|
2382
2451
|
for (const fragment of path.split('/')) {
|
|
2383
2452
|
if (!fragment) {
|