UNPKG

@nodefony/http-bundle

Version:

Nodefony Framework Bundle HTTP

229 lines (213 loc) 7.2 kB
let http2 = null; const https = require("https"); try { http2 = require("http2"); } catch (e) { http2 = null; } let quic = null; try { quic = require("net").createQuicSocket; } catch (e) { quic = null; } const protocol = { "1.1": https, "2.0": http2, "3.0": quic }; module.exports = class httpsServer extends nodefony.Service { constructor (httpKernel) { super("HTTPS", httpKernel.container, httpKernel.notificationsCenter); this.httpKernel = httpKernel; this.port = this.httpKernel.kernel.httpsPort; this.domain = this.httpKernel.kernel.settings.system.domain; this.ready = false; this.protocol = "2.0"; this.key = null; this.cert = null; this.ca = null; this.family = null; this.type = "HTTPS"; this.server = null; this.once("onBoot", async () => { this.bundle.on("onServersReady", (type) => { if (type === this.type) { const addr = this.server.address(); this.domain = addr.address; this.kernel.hostname = addr.address; this.port = addr.port; this.kernel.httpsPort = addr.port; this.kernel.hostHttps = `${this.kernel.hostname}:${addr.port}`; this.family = addr.family; this.log(`Listening on DOMAIN : https://${this.domain}:${this.port}`, "INFO"); /* dns.lookup(this.domain, (err, addresses, family) => { if (err) { throw err; } this.address = addresses; this.family = family; });*/ } }); }); } getCertificats () { this.settings = this.getParameters("bundles.http").https || null; this.settings.certificats = nodefony.extend(true, {}, this.settings.certificats, this.kernel.settings.system.servers.certificats); const bundleOptions = this.getParameters("bundles.http").https.certificats || null; const opt = nodefony.extend(true, { keyPath: this.kernel.checkPath(this.settings.certificats.key), certPath: this.kernel.checkPath(this.settings.certificats.cert), caPath: this.kernel.checkPath(this.settings.certificats.ca), key: null, cert: null, ca: null }, bundleOptions); try { this.key = fs.readFileSync(opt.keyPath); opt.key = this.key; this.cert = fs.readFileSync(opt.certPath); opt.cert = this.cert; if (opt.caPath) { this.ca = fs.readFileSync(opt.caPath); opt.ca = this.ca; } } catch (e) { throw e; } return opt; } createServer () { if (this.kernel.settings.system.servers.protocol in protocol) { this.protocol = this.kernel.settings.system.servers.protocol; } else { if (this.kernel.settings.system.servers.protocol) { this.log(`${this.kernel.settings.system.servers.protocol} not implemented `, "WARNING"); } else { this.log("BAD config servers https protocol not defined !! check framework config", "WARNING"); } this.protocol = "1.1"; } if (!http2) { this.protocol = "1.1"; } try { this.options = this.getCertificats(); for (const ele in this.options) { switch (ele) { case "keyPath": this.log(` READ CERTIFICATE KEY : ${this.options[ele]}`, "DEBUG"); break; case "certPath": this.log(` READ CERTIFICATE CERT : ${this.options[ele]}`, "DEBUG"); break; case "caPath": if (this.options[ele]) { this.log(` READ CERTIFICATE CA : ${this.options[ele]}`, "DEBUG"); } else { this.log(` NO CERTIFICATE CA : ${this.options[ele]}`, "WARNING"); } break; } } } catch (e) { this.log(e); throw e; } try { switch (this.protocol) { case "1.1": this.server = https.createServer(this.options); this.bundle.fire("onCreateServer", this.type, this); break; case "2.0": this.options.allowHTTP1 = true; this.settings2 = this.getParameters("bundles.http").http2 || {}; const buf = http2.getPackedSettings(this.settings2); this.defaultSetting2 = nodefony.extend({}, http2.getDefaultSettings(), http2.getUnpackedSettings(buf) || {}); this.server = http2.createSecureServer(this.options); this.bundle.fire("onCreateServer", this.type, this); this.server.on("sessionError", (error) => { this.log(error, "ERROR", "HTTP2 Server sessionError"); }); this.server.on("streamError", (error) => { this.log(error, "ERROR", "HTTP2 Server streamError"); }); break; default: } } catch (e) { this.log(e, "CRITIC"); throw e; } this.server.on("request", (request, response) => { const { socket: { alpnProtocol } } = request.httpVersion === "2.0" ? request.stream.session : request; if (alpnProtocol === "h2") { return this.httpKernel.onHttpRequest(request, response, "HTTP2"); } return this.httpKernel.onHttpRequest(request, response, this.type); }); if (this.settings.timeout) { this.server.timeout = this.settings.timeout; } if (this.settings.maxHeadersCount) { this.server.maxHeadersCount = this.settings.maxHeadersCount; } /* this.server.on('stream', (stream, hearder) => { //console.log("pass stream ") });*/ // LISTEN ON PORT this.server.listen(this.port, this.domain, () => { this.ready = true; this.bundle.fire("onServersReady", this.type, this); }); this.server.on("error", (error) => { const myError = new nodefony.Error(error); const txtError = typeof error.code === "string" ? error.code : error.errno; switch (txtError) { case "ENOTFOUND": this.log(`CHECK DOMAIN IN /etc/hosts or config unable to connect to : ${this.domain}`, "ERROR"); this.log(myError, "CRITIC"); break; case "EADDRINUSE": this.log(`Domain : ${this.domain} Port : ${this.port} ==> ALREADY USE `, "ERROR"); this.log(myError, "CRITIC"); this.server.close(); setTimeout(() => this.kernel.terminate(1), 1000); throw error; break; default: this.log(myError, "CRITIC"); } }); this.server.on("clientError", (e, socket) => { this.fire("onClientError", e, socket); }); this.once("onTerminate", () => new Promise((resolve, reject) => { if (this.server) { if (this.protocol === "2.0") { this.server.close(() => { this.log(`${this.type} SHUTDOWN Server HTTP2 is listening on DOMAIN : ${this.domain} PORT : ${this.port}`, "INFO"); // return resolve(true) }); return resolve(true); } this.server.closeAllConnections(); this.server.close(() => { this.log(`${this.type} SHUTDOWN Server HTTPS is listening on DOMAIN : ${this.domain} PORT : ${this.port}`, "INFO"); return resolve(true); }); return; } return resolve(true); })); return this.server; } };