|
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) |
|
} |
|
} |
|
} |
|
} |