xypriss 9.12.0 → 9.12.1
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/dist/cjs/src/server/core/SendFileHandler.js +53 -15
- package/dist/cjs/src/server/core/SendFileHandler.js.map +1 -1
- package/dist/cjs/src/server/core/XHSCProtocol.js +156 -418
- package/dist/cjs/src/server/core/XHSCProtocol.js.map +1 -1
- package/dist/cjs/src/server/core/XHSCRequest.js +516 -0
- package/dist/cjs/src/server/core/XHSCRequest.js.map +1 -0
- package/dist/cjs/src/server/core/XNullSocket.js +118 -0
- package/dist/cjs/src/server/core/XNullSocket.js.map +1 -0
- package/dist/cjs/src/xhsc/cluster/XHSCWorker.js +15 -20
- package/dist/cjs/src/xhsc/cluster/XHSCWorker.js.map +1 -1
- package/dist/esm/src/server/core/SendFileHandler.js +53 -15
- package/dist/esm/src/server/core/SendFileHandler.js.map +1 -1
- package/dist/esm/src/server/core/XHSCProtocol.js +157 -418
- package/dist/esm/src/server/core/XHSCProtocol.js.map +1 -1
- package/dist/esm/src/server/core/XHSCRequest.js +514 -0
- package/dist/esm/src/server/core/XHSCRequest.js.map +1 -0
- package/dist/esm/src/server/core/XNullSocket.js +116 -0
- package/dist/esm/src/server/core/XNullSocket.js.map +1 -0
- package/dist/esm/src/xhsc/cluster/XHSCWorker.js +15 -20
- package/dist/esm/src/xhsc/cluster/XHSCWorker.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var getSysApi = require('../../plugins/const/getSysApi.js');
|
|
3
4
|
var MIME_MAP = require('../const/MIME_MAP.js');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
5
|
+
var path = require('node:path');
|
|
6
|
+
var fs = require('node:fs');
|
|
6
7
|
|
|
7
8
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
9
|
// Resolve MIME type from file extension.
|
|
@@ -10,6 +11,7 @@ var promises = require('node:fs/promises');
|
|
|
10
11
|
function resolveMime(ext) {
|
|
11
12
|
return MIME_MAP.MIME_MAP[ext.toLowerCase()] ?? "application/octet-stream";
|
|
12
13
|
}
|
|
14
|
+
getSysApi.getSysApi();
|
|
13
15
|
class SendFileHandler {
|
|
14
16
|
constructor(res, logger) {
|
|
15
17
|
this.res = res;
|
|
@@ -18,33 +20,69 @@ class SendFileHandler {
|
|
|
18
20
|
async handle(filePath, options = {}) {
|
|
19
21
|
try {
|
|
20
22
|
const finalPath = options.root
|
|
21
|
-
?
|
|
23
|
+
? path.join(options.root, filePath)
|
|
22
24
|
: filePath;
|
|
23
25
|
// Resolve absolute path to ensure Go can access it
|
|
24
|
-
const absolutePath =
|
|
26
|
+
const absolutePath = path.isAbsolute(finalPath)
|
|
25
27
|
? finalPath
|
|
26
|
-
:
|
|
27
|
-
try {
|
|
28
|
-
await promises.stat(absolutePath);
|
|
29
|
-
}
|
|
30
|
-
catch (e) {
|
|
31
|
-
throw { code: "ENOENT", message: "File not found" };
|
|
32
|
-
}
|
|
28
|
+
: path.resolve(process.cwd(), finalPath);
|
|
33
29
|
const req = this.res.req;
|
|
34
30
|
const requestId = req?.id;
|
|
35
31
|
const worker = req?.app?._xhscWorker;
|
|
36
|
-
if (requestId && worker
|
|
32
|
+
if (requestId && worker) {
|
|
37
33
|
if (this.logger) {
|
|
38
34
|
this.logger.debug("server", `[SendFileHandler] Delegating "${absolutePath}" to XHSC Core (Req: ${requestId})`);
|
|
39
35
|
}
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
/**
|
|
37
|
+
* @performance XHSC Zero-Copy Static File Delegation
|
|
38
|
+
*
|
|
39
|
+
* By delegating immediately to the XHSC (Go) engine *before* performing
|
|
40
|
+
* `fs.stat()` in Node.js, we eliminate a major performance bottleneck.
|
|
41
|
+
* Node.js relies on a limited thread pool (default 4) for async file system
|
|
42
|
+
* operations. Under heavy concurrent load, synchronous-like `stat` calls
|
|
43
|
+
* exhaust this pool and queue up, causing multi-second latency spikes.
|
|
44
|
+
*
|
|
45
|
+
* Delegating to Go offloads file existence checking, MIME resolution,
|
|
46
|
+
* ETags, Range headers, and the actual native `sendfile` zero-copy stream
|
|
47
|
+
* completely to the core engine. If the file does not exist, Go will
|
|
48
|
+
* natively return an HTTP 404 response.
|
|
49
|
+
*/
|
|
50
|
+
// Embed options natively into headers so they serialize via XBP
|
|
51
|
+
this.res.setHeader("x-xhsc-static-delegate", absolutePath);
|
|
52
|
+
if (options.headers) {
|
|
53
|
+
for (const [k, v] of Object.entries(options.headers)) {
|
|
54
|
+
this.res.setHeader(k, v);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (options.maxAge) {
|
|
58
|
+
this.res.setHeader("Cache-Control", `public, max-age=${Math.floor(options.maxAge / 1000)}`);
|
|
59
|
+
}
|
|
60
|
+
if (options.disposition) {
|
|
61
|
+
if (options.disposition === "inline") {
|
|
62
|
+
this.res.setHeader("Content-Disposition", "inline");
|
|
63
|
+
}
|
|
64
|
+
else if (options.disposition === "attachment") {
|
|
65
|
+
this.res.setHeader("Content-Disposition", `attachment; filename="${path.basename(absolutePath)}"`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.res.setHeader("Content-Disposition", `attachment; filename="${options.disposition}"`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (options.mimeOverrides) {
|
|
72
|
+
const ext = path.extname(absolutePath);
|
|
73
|
+
if (options.mimeOverrides[ext]) {
|
|
74
|
+
this.res.setHeader("Content-Type", options.mimeOverrides[ext]);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
42
77
|
// Mark as delegated by setting status 0.
|
|
43
78
|
// XHSCBridge/index.ts and XHSCWorker.ts handle this state.
|
|
44
79
|
this.res.statusCode = 0;
|
|
45
80
|
this.res.end();
|
|
46
81
|
return;
|
|
47
82
|
}
|
|
83
|
+
if (!fs.existsSync(absolutePath) || !fs.statSync(absolutePath).isFile()) {
|
|
84
|
+
throw { code: "ENOENT", message: "File not found" };
|
|
85
|
+
}
|
|
48
86
|
// Fallback if not running under XHSC Bridge (should not happen in production)
|
|
49
87
|
this.logger?.warn("server", "[SendFileHandler] XHSC Bridge not found, falling back to manual stream");
|
|
50
88
|
this._streamFile(absolutePath);
|
|
@@ -66,7 +104,7 @@ class SendFileHandler {
|
|
|
66
104
|
}
|
|
67
105
|
}
|
|
68
106
|
_streamFile(filePath, start, end) {
|
|
69
|
-
const stream =
|
|
107
|
+
const stream = fs.createReadStream(filePath, { start, end });
|
|
70
108
|
stream.pipe(this.res);
|
|
71
109
|
}
|
|
72
110
|
static registerMimeTypes(types) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SendFileHandler.js","sources":["../../../../../src/server/core/SendFileHandler.ts"],"sourcesContent":[null],"names":["MIME_MAP","
|
|
1
|
+
{"version":3,"file":"SendFileHandler.js","sources":["../../../../../src/server/core/SendFileHandler.ts"],"sourcesContent":[null],"names":["MIME_MAP","getSysApi"],"mappings":"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"}
|