UNPKG

modernirc

Version:

IRC library for creating modern IRC bots

81 lines (72 loc) 2.3 kB
/** * API for Webapp controller * * It answers HTTP requests to control the data from and to the bot. * In order to achieve that, the bot must be able to send its details to the API. */ import http from 'node:http' import { URL } from 'node:url' import qs from 'node:querystring' import { workerData } from 'node:worker_threads' import routes from './routes.js' import { createLogger } from '../log.js' /** * HTTP API request handler * @param logger {object} Logger * @param req {import('node:http').IncomingMessage} * @param res {import('node:http').ServerResponse} * @returns {Promise<*>} */ async function handler(logger, req, res) { req._url = URL.parse(req.url, `https://${req.headers.host}`) if (['post', 'put', 'patch'].includes(req.method.toLowerCase())) { req.body = await new Promise((resolve, reject) => { let data = '' req.on('data', (chunk) => { data += chunk.toString() }).on('end', () => { if (req.headers['content-type']?.startsWith('application/json')) { return resolve(JSON.parse(data)) } if (req.headers['content-type']?.startsWith('application/x-www-form-urlencoded')) { return resolve(qs.parse(data)) } return resolve(data) }).on('error', reject) }) } else { req.body = null } req.logger = logger const key = req.headers['x-key'] if (!key || key !== workerData.opts.auth.key) { res.writeHead(403) return res.end('Forbidden Access') } const eligibleRoute = routes.find((route) => { return route.path === req._url.pathname && req.method.toLowerCase() === route.method }) if (!eligibleRoute) { res.writeHead(404) return res.end('Not Found') } const result = await eligibleRoute.handler(req) const resultData = JSON.stringify(result.data) res.writeHead(result.statusCode, { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(resultData), }) return res.end(resultData) } function main() { const logger = createLogger({ ...workerData.logger, name: 'api', }) const srv = http.createServer((req, res) => handler(logger, req, res)) const port = workerData.opts.listen?.port ?? 9999 srv.listen(port, () => { logger.info(`listening on port ${port}`) }) } main()