GT-Manual / lib /loader /listener.js
wuliya's picture
upload
072e993
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)
}
}
}
}