Files
Tiber365/node_modules/crossws/dist/adapters/node.mjs
2025-07-24 18:46:24 +02:00

164 lines
4.4 KiB
JavaScript

import { M as Message, P as Peer, t as toBufferLike } from '../shared/crossws.DfCzGthR.mjs';
import { A as AdapterHookable, a as adapterUtils } from '../shared/crossws.D9ehKjSh.mjs';
import { W as WSError } from '../shared/crossws.By9qWDAI.mjs';
import { _ as _WebSocketServer } from '../shared/crossws.CipVM6lf.mjs';
import 'uncrypto';
import 'stream';
import 'events';
import 'http';
import 'crypto';
import 'buffer';
import 'zlib';
import 'https';
import 'net';
import 'tls';
import 'url';
const nodeAdapter = (options = {}) => {
const hooks = new AdapterHookable(options);
const peers = /* @__PURE__ */ new Set();
const wss = options.wss || new _WebSocketServer({
noServer: true,
...options.serverOptions
});
wss.on("connection", (ws, nodeReq) => {
const request = new NodeReqProxy(nodeReq);
const peer = new NodePeer({ ws, request, peers, nodeReq });
peers.add(peer);
hooks.callHook("open", peer);
ws.on("message", (data) => {
if (Array.isArray(data)) {
data = Buffer.concat(data);
}
hooks.callHook("message", peer, new Message(data, peer));
});
ws.on("error", (error) => {
peers.delete(peer);
hooks.callHook("error", peer, new WSError(error));
});
ws.on("close", (code, reason) => {
peers.delete(peer);
hooks.callHook("close", peer, {
code,
reason: reason?.toString()
});
});
});
wss.on("headers", (outgoingHeaders, req) => {
const upgradeHeaders = req._upgradeHeaders;
if (upgradeHeaders) {
for (const [key, value] of new Headers(upgradeHeaders)) {
outgoingHeaders.push(`${key}: ${value}`);
}
}
});
return {
...adapterUtils(peers),
handleUpgrade: async (nodeReq, socket, head) => {
const request = new NodeReqProxy(nodeReq);
const { upgradeHeaders, endResponse, context } = await hooks.upgrade(request);
if (endResponse) {
return sendResponse(socket, endResponse);
}
nodeReq._request = request;
nodeReq._upgradeHeaders = upgradeHeaders;
nodeReq._context = context;
wss.handleUpgrade(nodeReq, socket, head, (ws) => {
wss.emit("connection", ws, nodeReq);
});
},
closeAll: (code, data, force) => {
for (const client of wss.clients) {
if (force) {
client.terminate();
} else {
client.close(code, data);
}
}
}
};
};
class NodePeer extends Peer {
get remoteAddress() {
return this._internal.nodeReq.socket?.remoteAddress;
}
get context() {
return this._internal.nodeReq._context;
}
send(data, options) {
const dataBuff = toBufferLike(data);
const isBinary = typeof dataBuff !== "string";
this._internal.ws.send(dataBuff, {
compress: options?.compress,
binary: isBinary,
...options
});
return 0;
}
publish(topic, data, options) {
const dataBuff = toBufferLike(data);
const isBinary = typeof data !== "string";
const sendOptions = {
compress: options?.compress,
binary: isBinary,
...options
};
for (const peer of this._internal.peers) {
if (peer !== this && peer._topics.has(topic)) {
peer._internal.ws.send(dataBuff, sendOptions);
}
}
}
close(code, data) {
this._internal.ws.close(code, data);
}
terminate() {
this._internal.ws.terminate();
}
}
class NodeReqProxy {
_req;
_headers;
_url;
constructor(req) {
this._req = req;
}
get url() {
if (!this._url) {
const req = this._req;
const host = req.headers["host"] || "localhost";
const isSecure = req.socket?.encrypted ?? req.headers["x-forwarded-proto"] === "https";
this._url = `${isSecure ? "https" : "http"}://${host}${req.url}`;
}
return this._url;
}
get headers() {
if (!this._headers) {
this._headers = new Headers(this._req.headers);
}
return this._headers;
}
}
async function sendResponse(socket, res) {
const head = [
`HTTP/1.1 ${res.status || 200} ${res.statusText || ""}`,
...[...res.headers.entries()].map(
([key, value]) => `${encodeURIComponent(key)}: ${encodeURIComponent(value)}`
)
];
socket.write(head.join("\r\n") + "\r\n\r\n");
if (res.body) {
for await (const chunk of res.body) {
socket.write(chunk);
}
}
return new Promise((resolve) => {
socket.end(() => {
socket.destroy();
resolve();
});
});
}
export { nodeAdapter as default };