Spaces:
Sleeping
Sleeping
import PluginsLoader from './loader.js' | |
import Plugin from '../plugin.js' | |
import application from './application.js' | |
import { WebSocketServer } from 'ws' | |
import util from 'node:util' | |
import path from 'node:path' | |
import http from 'node:http' | |
import https from 'node:https' | |
export default class ListenerLoader extends PluginsLoader { | |
constructor () { | |
global.plugin = Plugin | |
super() | |
} | |
static create (args) { | |
let cfg = args.cfg | |
if (!cfg.http.HTTPS) { | |
args.server = http.createServer(args.app) | |
} else { | |
args.server = https.createServer(cfg.cert, args.app) | |
if (cfg.http.HTTP_TO_HTTPS) { | |
http.createServer((req, res) => { | |
res.writeHead(307, { | |
'Location': cfg.https_address(req.url, req.headers.host) | |
}).end() | |
}).listen(cfg.http.HTTP_PORT) | |
} | |
} | |
args.handler = application.Handle(args.app) | |
args.wss = new WebSocketServer({ server: args.server }) | |
return Object.assign(new ListenerLoader(), args) | |
} | |
async run () { | |
this.wss.on('error', logger.error) | |
this.wss.on('connection', (socket, request) => { | |
if ('upgradeReq' in socket) { | |
request = socket.upgradeReq | |
} | |
request.ws = socket | |
request.url = this.handler.WebSocketUrl(request.url) | |
this.handler.call(request.url.split('?')[0], [socket, request], () => { | |
if (!request.wsHandled) socket.close() | |
}) | |
}) | |
await this.pluginsLoader() | |
await this.addListener() | |
this.server.listen(...this.cfg.http_listen) | |
} | |
async addListener () { | |
this.cfg.paths = {} | |
for (let plugin of this.priority) { | |
if (plugin.rule) { | |
for (let v of plugin.rule) { | |
let middlewares = [] | |
let path = ((plugin.self.route || '') + (v.path || '')) || '/' | |
if (v.use) { | |
if (typeof v.use == 'string' && plugin.self[v.use]) { | |
let result = await plugin.self[v.use]() | |
if (result) { | |
if (!util.isArray(result)) { | |
result = [result] | |
} | |
middlewares.push(...result) | |
} | |
} else if (util.isArray(v.use)) { | |
v.use.forEach(fn => { | |
if (fn && plugin.self[fn]) { | |
middlewares.push(plugin.self[fn]) | |
} | |
}) | |
} | |
} | |
if (v.fnc && plugin.self[v.fnc]) { | |
if (v.method == 'ws') { | |
middlewares.push(this.WebSocketEvent(plugin, v.fnc)) | |
} else { | |
middlewares.push(this.HttpRequestEvent(plugin, v.fnc)) | |
} | |
} | |
this.app[v.method](path, middlewares) | |
} | |
} | |
} | |
} | |
HttpRequestEvent (plugin, fnc) { | |
return async (req, res, next) => { | |
let p = (this.priority.find(val => val.key == plugin.key))?.class | |
if (!p) return res.send({ status: 1, message: 'Error occurred!' }) | |
let t = { | |
req, res, next, | |
param: req.params, | |
query: req.query, | |
cookie: req.cookies, | |
body: req.body, | |
end: res.end, | |
send: (data, status) => res.status(status || 200).send(data), | |
error: (msg, status) => res.status(status || 200).send({ status: 1, message: msg || 'Invalid request' }), | |
render: res.render | |
} | |
t.params = Object.assign({}, t.param, t.query, t.body, t.cookie) | |
let self = Object.assign(new p(), t) | |
try { | |
let res = self[fnc] && self[fnc]() | |
if (util.types.isPromise(res)) { | |
res = await res | |
} | |
} catch (err) { | |
if (err) logger.error(err) | |
} | |
} | |
} | |
WebSocketEvent (plugin, fnc) { | |
return async (socket, request, next) => { | |
let p = (this.priority.find(val => val.key == plugin.key))?.class | |
if (!p) return socket.close() | |
let t = { | |
socket, request, next, | |
send: (...args) => socket.send(...args), | |
close: () => socket.close(), | |
onMessage: (fn, on = 'on') => socket[on]('message', fn), | |
onClose: (fn, on = 'on') => socket[on]('close', fn), | |
onError: (fn, on = 'on') => socket[on]('error', fn) | |
} | |
let self = Object.assign(new p(), t) | |
self.onError(logger.error) | |
try { | |
let res = self[fnc] && self[fnc]() | |
if (util.types.isPromise(res)) { | |
res = await res | |
} | |
} catch (err) { | |
if (err) logger.error(err) | |
} | |
} | |
} | |
} |