minimalistic-server 0.0.61 → 0.0.62
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 +33 -16
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import * as http from 'node:http';
|
|
|
2
2
|
import * as querystring from "node:querystring";
|
|
3
3
|
import * as fs from "node:fs/promises";
|
|
4
4
|
import * as tls from "node:tls";
|
|
5
|
+
import * as net from "node:net";
|
|
5
6
|
import * as nodeCrypto from "node:crypto";
|
|
6
7
|
|
|
7
8
|
const servers = new Map();
|
|
@@ -881,10 +882,12 @@ export class Request {
|
|
|
881
882
|
#request;
|
|
882
883
|
#customData = null;
|
|
883
884
|
#webSocketData = null;
|
|
885
|
+
#heads = null;
|
|
884
886
|
#isWebSocketClosed = false;
|
|
885
887
|
|
|
886
|
-
constructor(request) {
|
|
888
|
+
constructor(request, heads = null) {
|
|
887
889
|
this.#request = request;
|
|
890
|
+
this.#heads = heads;
|
|
888
891
|
|
|
889
892
|
let url = new URL(`http://localhost${request.url}`);
|
|
890
893
|
|
|
@@ -902,7 +905,7 @@ export class Request {
|
|
|
902
905
|
}
|
|
903
906
|
|
|
904
907
|
isAlive() {
|
|
905
|
-
return this.#request.socket.
|
|
908
|
+
return !(this.#request.socket.writableEnded || this.#request.socket.destroyed);
|
|
906
909
|
}
|
|
907
910
|
|
|
908
911
|
getMethod() {
|
|
@@ -1289,10 +1292,12 @@ export class Request {
|
|
|
1289
1292
|
});
|
|
1290
1293
|
|
|
1291
1294
|
socket.on("error", (error) => {
|
|
1295
|
+
safePrint(error);
|
|
1292
1296
|
resolve();
|
|
1293
1297
|
});
|
|
1294
1298
|
|
|
1295
1299
|
socket.on('timeout', (error) => {
|
|
1300
|
+
safePrint(error);
|
|
1296
1301
|
resolve();
|
|
1297
1302
|
});
|
|
1298
1303
|
})
|
|
@@ -1352,7 +1357,7 @@ export class Request {
|
|
|
1352
1357
|
listeners: new Set(),
|
|
1353
1358
|
nextDataPromiseWithResolvers: null,
|
|
1354
1359
|
isManuallyClosed: false,
|
|
1355
|
-
collectedData: [],
|
|
1360
|
+
collectedData: this.#heads?.length ? [this.#heads] : [],
|
|
1356
1361
|
};
|
|
1357
1362
|
|
|
1358
1363
|
const guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
@@ -1361,8 +1366,8 @@ export class Request {
|
|
|
1361
1366
|
const validHandShakeKey = sha1.digest("base64");
|
|
1362
1367
|
|
|
1363
1368
|
const responseHeaders = [
|
|
1364
|
-
"HTTP/1.1 101
|
|
1365
|
-
"Upgrade:
|
|
1369
|
+
"HTTP/1.1 101 Switching Protocols",
|
|
1370
|
+
"Upgrade: websocket",
|
|
1366
1371
|
"Connection: Upgrade",
|
|
1367
1372
|
`Sec-WebSocket-Accept: ${validHandShakeKey}`,
|
|
1368
1373
|
"\r\n",
|
|
@@ -1489,7 +1494,7 @@ export class Request {
|
|
|
1489
1494
|
if (this.#webSocketData.isManuallyClosed) {
|
|
1490
1495
|
await sendDataToAllListeners(null, 'end');
|
|
1491
1496
|
} else {
|
|
1492
|
-
await sendDataToAllListeners(error, '
|
|
1497
|
+
await sendDataToAllListeners(error, 'error');
|
|
1493
1498
|
}
|
|
1494
1499
|
}
|
|
1495
1500
|
}
|
|
@@ -1820,11 +1825,11 @@ export class FileResponse extends Response {
|
|
|
1820
1825
|
.map(x => {
|
|
1821
1826
|
x = +x;
|
|
1822
1827
|
|
|
1823
|
-
if (!
|
|
1828
|
+
if (!Number.isSafeInteger(x)) {
|
|
1824
1829
|
return null;
|
|
1825
1830
|
}
|
|
1826
1831
|
|
|
1827
|
-
return
|
|
1832
|
+
return x;
|
|
1828
1833
|
});
|
|
1829
1834
|
|
|
1830
1835
|
const data = await this.#retreiveData();
|
|
@@ -2134,9 +2139,9 @@ export function serve(routes, port = 80, staticFileDirectoryOrDirectories = null
|
|
|
2134
2139
|
unserve(port);
|
|
2135
2140
|
|
|
2136
2141
|
|
|
2137
|
-
const callback = async (req, res) => {
|
|
2142
|
+
const callback = async (req, res, heads = null) => {
|
|
2138
2143
|
try {
|
|
2139
|
-
const [code, headers, body, isHandledAsWebSocket] = await handleRequest(req, routes, staticFileDirectoryOrDirectories, handleNotFoundError);
|
|
2144
|
+
const [code, headers, body, isHandledAsWebSocket] = await handleRequest(req, routes, staticFileDirectoryOrDirectories, handleNotFoundError, heads);
|
|
2140
2145
|
|
|
2141
2146
|
if (isHandledAsWebSocket || !(res instanceof http.ServerResponse)) {
|
|
2142
2147
|
return;
|
|
@@ -2146,25 +2151,37 @@ export function serve(routes, port = 80, staticFileDirectoryOrDirectories = null
|
|
|
2146
2151
|
|
|
2147
2152
|
if (typeof body === 'function') {
|
|
2148
2153
|
for await (const chunk of body()) {
|
|
2149
|
-
if (res.
|
|
2154
|
+
if (res.writableEnded || res.destroyed) {
|
|
2150
2155
|
break;
|
|
2151
2156
|
}
|
|
2152
2157
|
|
|
2153
2158
|
res.write(chunk);
|
|
2154
2159
|
let waitTime = 0;
|
|
2155
2160
|
|
|
2156
|
-
while (res.writableNeedDrain && !res.
|
|
2161
|
+
while (res.writableNeedDrain && !res.writableEnded && !res.destroyed && waitTime < keepAliveTimeout) {
|
|
2157
2162
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
2158
2163
|
waitTime += 50;
|
|
2159
2164
|
}
|
|
2160
2165
|
}
|
|
2161
2166
|
} else {
|
|
2162
|
-
res.
|
|
2167
|
+
res.end(body);
|
|
2163
2168
|
}
|
|
2164
2169
|
} catch (error) {
|
|
2165
2170
|
safePrint(error, true);
|
|
2166
2171
|
} finally {
|
|
2167
|
-
res.
|
|
2172
|
+
if (res instanceof net.Socket) {
|
|
2173
|
+
if (!res.writableEnded) {
|
|
2174
|
+
res.end();
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
2178
|
+
|
|
2179
|
+
if (!res.destroyed) {
|
|
2180
|
+
res.destroy();
|
|
2181
|
+
}
|
|
2182
|
+
} else if (res instanceof http.ServerResponse && !res.writableEnded && !res.destroyed) {
|
|
2183
|
+
res.end();
|
|
2184
|
+
}
|
|
2168
2185
|
}
|
|
2169
2186
|
};
|
|
2170
2187
|
|
|
@@ -2408,7 +2425,7 @@ function invalidateStaticCache(path = null, clear = true) {
|
|
|
2408
2425
|
}
|
|
2409
2426
|
}
|
|
2410
2427
|
|
|
2411
|
-
async function handleRequest(req, routes, staticFileDirectories, handleNotFoundError) {
|
|
2428
|
+
async function handleRequest(req, routes, staticFileDirectories, handleNotFoundError, heads) {
|
|
2412
2429
|
let response = new JsonResponse({
|
|
2413
2430
|
message: 'Invalid data'
|
|
2414
2431
|
}, 400);
|
|
@@ -2417,7 +2434,7 @@ async function handleRequest(req, routes, staticFileDirectories, handleNotFoundE
|
|
|
2417
2434
|
let responseBodyIsIncluded = true;
|
|
2418
2435
|
|
|
2419
2436
|
try {
|
|
2420
|
-
const request = new Request(req);
|
|
2437
|
+
const request = new Request(req, heads);
|
|
2421
2438
|
|
|
2422
2439
|
const method = request.getMethod();
|
|
2423
2440
|
const path = request.getPath();
|