UNPKG

fastify-uws

Version:

A performant HTTP and WebSocket server for Fastify with uWebSockets.

106 lines (105 loc) 3.44 kB
import f from "uWebSockets.js"; import v from "node:dns/promises"; import { METHODS as L } from "node:http"; import { EventEmitter as N } from "eventemitter3"; import H from "ipaddr.js"; import { ERR_SERVER_DESTROYED as I, ERR_SOCKET_BAD_PORT as y, ERR_ENOTFOUND as O, ERR_INVALID_METHOD as C, ERR_ADDRINUSE as M } from "./errors.js"; import { HTTPSocket as P } from "./http-socket.js"; import { Request as x } from "./request.js"; import { Response as b } from "./response.js"; import { kHandler as R, kHttps as w, kWs as r, kAddress as s, kListenSocket as l, kApp as g, kClosed as d, kListenAll as A, kListening as a, kListen as S, kClientError as V } from "./symbols.js"; function q(n) { return n.http2 && n.https ? f.SSLApp({ key_file_name: n.https.key.toString("utf-8"), cert_file_name: n.https.cert.toString("utf-8") }) : f.App(); } const U = new Map(L.map((n) => [n.toLowerCase(), n])), c = {}; class X extends N { [R]; timeout; [w]; [r]; [s]; [l]; [g]; [d]; [A]; [a]; constructor(t, e = {}) { super(); const { http2: o = !1, https: u = null, connectionTimeout: p = 0 } = e; this[R] = t, this.timeout = p, this[w] = u, this[r] = null, this[s] = null, this[l] = null, this[g] = q({ http2: o, https: u }), this[d] = !1; } get encrypted() { return !!this[w]; } get listening() { return this[a]; } setTimeout(t) { this.timeout = t; } address() { return this[s]; } listen(t, e) { t?.signal && t.signal.addEventListener("abort", () => { this.close(); }), this[S](t).then(() => { e?.(), this[a] = !0, this.emit("listening"); }).catch((o) => { this[s] = null, process.nextTick(() => this.emit("error", o)); }); } closeIdleConnections() { this.close(); } close(t = () => { }) { if (this[s] = null, this[a] = !1, this[d]) return t(); const e = this[s]?.port; if (e !== void 0 && c[e] === this && delete c[e], this[s] = null, this[d] = !0, this[l] && (f.us_listen_socket_close(this[l]), this[l] = null), this[r]) for (const o of this[r].connections) o.close(); process.nextTick(() => { this.emit("close"), t(); }); } ref() { } unref() { } async [S]({ port: t, host: e }) { if (this[d]) throw new I(); if (t != null && Number.isNaN(Number(t))) throw new y(t); t = t == null ? 0 : Number(t); const o = await v.lookup(e); if (this[s] = { ...o, port: t }, this[s].address.startsWith("[")) throw new O(this[s].address); const u = H.parse(this[s].address); this[s].family = u.kind() === "ipv6" ? "IPv6" : "IPv4"; const p = u.toNormalizedString(), E = this[g], T = (k, m) => { const h = U.get(m.getMethod()), i = new P(this, k, h === "GET" || h === "HEAD"); if (!h) { i[V] = !0, this.emit("clientError", new C(), i); return; } const _ = new x(m, i, h), D = new b(i); _.headers.upgrade && this.emit("upgrade", _, i), this[R](_, D); }; return E.any("/*", T), t !== 0 && c[t] && (this[r] = c[t][r]), this[r] && this[r].addServer(this), new Promise((k, m) => { const h = (i) => { if (!i) return m(new M(this[s].address, t)); this[l] = i, t = this[s].port = f.us_socket_local_port(i), c[t] || (c[t] = this), k(); }; this[A] = e === "localhost", this[A] ? E.listen(t, h) : E.listen(p, t, h); }); } } export { X as Server };