UNPKG

kirito.cloudflared.subservice

Version:

Kirito Cloudflared e ótimo para criar tunnels da cloudflared para expor a sua aplicação a internet.

232 lines (198 loc) 6.26 kB
const { bin, install, Tunnel } = require("cloudflared"); const { getServers, setServers, lookup } = require("dns"); const { existsSync } = require("fs"); const { EventEmitter } = require("events"); const { Timer } = require("@gibme/timer"); const fetch = require("@gibme/fetch").default; class Cloudflared extends EventEmitter { constructor(local_url, check_interval = 2000) { super(); this.local_url = local_url; this.system_dns_servers = getServers(); this._connections = new Set(); this._dns_ready = false; this._https_ready = false; setServers([ ...this.system_dns_servers, "1.1.1.1", "8.8.8.8", "9.9.9.9" ]); this.dns_servers = getServers(); this.dns_timer = new Timer(check_interval, true); this.https_timer = new Timer(check_interval, true); this.ready_timer = new Timer(check_interval, true); this.dns_timer.on("tick", async () => { if (this.hostname) { if (await this.dns_exists()) { this._dns_ready = true; this.emit("subservice", { timestamp: new Date(), url: this.url, hostname: this.hostname, connections: this.connections, type: "dns" }); this.dns_timer.destroy(); } else { this.emit("progress", { timestamp: new Date(), url: this.url, hostname: this.hostname, connections: this.connections, type: "dns", status: "not_ready" }); } } }); this.https_timer.on("tick", async () => { if (this.hostname) { if (await this.https_exists()) { this._https_ready = true; this.emit("subservice", { timestamp: new Date(), url: this.url, hostname: this.hostname, connections: this.connections, type: "https" }); this.https_timer.destroy(); } else { this.emit("progress", { timestamp: new Date(), url: this.url, hostname: this.hostname, connections: this.connections, type: "https", status: "not_ready" }); } } }); this.ready_timer.on("tick", async () => { if (this.ready) { this.emit("ready", { timestamp: new Date(), url: this.url, hostname: this.hostname, connections: this.connections }); this.ready_timer.destroy(); } }); } get url() { return this._url; } get hostname() { return this._hostname; } get connections() { return this._connections; } get dns_ready() { return this._dns_ready; } get https_ready() { return this._https_ready; } get ready() { return !!this._url; //return this.dns_ready && this.https_ready; } get tunnel() { return this._tunnel; } static async install_cloudflared() { try { if (!existsSync(bin)) { await install(bin); } return bin; } catch (_) { return null; } } on(event, listener) { return super.on(event, listener); } once(event, listener) { return super.once(event, listener); } off(event, listener) { return super.off(event, listener); } async start(timeout = 30000) { if (this.tunnel) return true; if (!(await Cloudflared.install_cloudflared())) return false; this._timeout = setTimeout(() => { if (!this.ready) { this.stop(); this.emit("timeout", new Error("Tunnel could not be started within the given timeout.")); } }, timeout); try { this._tunnel = Tunnel.quick(this.local_url); this._tunnel.once("url", (url) => { this._url = url; this._hostname = new URL(url).hostname; }); this._tunnel.once("connected", (connection) => { this._connections.clear(); this._connections.add(connection); }); this.emit("started"); return true; } catch (_) { this.cleanup(); return false; } } async stop() { this.cleanup(); if (!this.tunnel) return true; try { this.tunnel.process.kill("SIGINT"); } catch (_) {} try { this.tunnel.process.kill(); } catch (_) {} const result = this.tunnel.stop(); delete this._tunnel; this.emit("stopped"); return result; } cleanup() { this.dns_timer.destroy(); this.https_timer.destroy(); this.ready_timer.destroy(); delete this._hostname; this._connections.clear(); delete this._url; } async https_exists() { try { if (this.url) { await fetch.get(this.url); return true; } else { return false; } } catch (_) { return false; } } async dns_exists() { return new Promise((resolve) => { if (this.hostname) { lookup(this.hostname, (error) => { resolve(!error); }); } else { resolve(false); } }); } } module.exports = Cloudflared;