{"version":3,"sources":["jsdelivr-header.js","/npm/@superhero/http-server@4.8.6/index.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,OCNO,SAAoB,qCACpB,WAAoB,2BACpB,QAAoB,wBACpB,kBAAoB,sCACpB,SAAoB,mBACpB,UAAoB,oBACpB,UAAoB,oBACpB,QAAoB,kBACpB,QAAoB,kBAClB,QAAkB,kBAEpB,SAAS,OAAO,GAErB,MAAM,EAAS,IAAI,OAAO,GAC1B,OAAO,IAAI,WAAW,EACxB,gBAEe,MAAM,WAInB,MAAO,IAAI,eAAgB,eAAe,cAI1C,WAAc,GACd,UAAc,GACd,UAAc,GACd,WAAc,GAGd,IAAM,IAAI,IAAI,CAAE,MAAO,gBAAgB,KAAK,UAG5C,GAAY,IAAI,IAEhB,WAAA,CAAY,GAEV,KAAK,OAAS,CAChB,CAEA,eAAM,CAAU,GAEd,OAAO,OAAO,KAAK,IAAI,OAAQ,GAAU,KAEzC,MACE,EAAiB,GAAU,QAAQ,QAAU,CAAC,EAC9C,EAAiB,OAAO,OAAO,CAAC,EAAG,GAAU,QAE/C,KAAK,OAAO,UAAU,EAAQ,GAAU,QAAQ,YAE7C,EAAe,KACf,EAAe,KACf,EAAe,KAEhB,MAAK,EAAwB,GAI7B,MAAK,EAA2B,GAGlC,KAAK,YAAY,GAAG,UAAW,KAAK,WAAW,KAAK,OACpD,KAAK,QAAQ,GAAG,SAAS,IAAM,cAAa,IAAM,KAAK,IAAI,IAAI,aAC/D,KAAK,QAAQ,GAAG,QAAS,MAAK,EAAe,KAAK,MACpD,CAEA,YAAM,IAAU,SAER,IAAI,SAAQ,CAAC,EAAQ,KAEzB,GAAG,KAAK,QACR,CACE,MACE,EAAW,KAAQ,KAAK,QAAQ,IAAI,QAAa,GAAW,GAAO,EACnE,EAAW,KAAQ,KAAK,QAAQ,IAAI,YAAa,GAAW,GAAO,EAErE,KAAK,QAAQ,KAAK,QAAa,GAC/B,KAAK,QAAQ,KAAK,YAAa,GAE/B,KAAK,QAAQ,UAAU,EACzB,MAGE,MAAK,EAAsB,EAC7B,IAIF,MAAM,KAAE,GAAS,KAAK,QAAQ,UAC9B,KAAK,IAAI,IAAI,QAAQ,eACvB,CAEA,WAAM,SAGE,IAAI,SAAQ,CAAC,EAAQ,IACzB,KAAK,QACH,KAAK,QAAQ,OAAO,GAClB,EACE,EAAO,GACP,aAAa,KACjB,MAAK,EAAsB,KAG/B,IAAI,MAAM,KAAW,MAAK,QAClB,IAAI,SAAS,GACjB,EAAQ,OACN,IACA,EAAQ,MAAM,IACtB,CAEA,UAAA,CAAW,IAEN,IAAU,EAAQ,SAEnB,EAAQ,GAAK,MAAK,IAElB,EAAQ,GAAG,SAAS,IAAM,KAAK,IAAI,IAAI,GAAG,EAAQ,gBAClD,EAAQ,GAAG,SAAS,IAAM,MAAK,EAAU,OAAO,KAChD,EAAQ,GAAG,SAAU,GAAU,KAAK,IAAI,IAAI,GAAG,MAC/C,MAAK,EAAU,IAAI,GACnB,KAAK,IAAI,IAAI,GAAG,EAAQ,eAE5B,CAKA,SAAgC,OAAO,KAAK,oCAM5C,OAAM,CAAa,GAEjB,IAAI,EAEJ,EACA,CACE,GAAG,EAAO,UAER,OAAO,OAAO,MAAM,GAGtB,GAAG,EAAU,EAAO,KAAK,YAAW,EAAuB,QAEzD,OAAO,QAGH,IAAI,SAAS,GAAW,QAAQ,SAAS,IACjD,OACM,OAAS,EACjB,CAEA,EAAA,CAAqB,EAAe,EAAe,GAEjD,EAAO,KAAK,YAAY,UAEtB,MAAM,QAAgB,MAAK,EAAa,GAExC,aAAa,GACb,EAAO,QAAQ,GAEf,EAAQ,OAAO,YAAW,GACxB,EAAc,GACd,EAAc,EAAM,IAGxB,MAAM,EAAU,WAAW,EAAO,QAAQ,KAAK,GAAS,IAC1D,CAEA,EAAA,CAAgC,GAE9B,KAAK,YAAY,KAAK,aAAc,EACtC,CAEA,EAAA,CAAgC,GAE9B,KAAK,YAAY,KAAK,aAAc,EACtC,CAEA,EAAA,CAAsC,GAEpC,KAAK,YAAY,KAAK,mBAAoB,EAC5C,CAEA,EAAA,CAAsC,GAKpC,MAAM,EAAU,MAAM,uBAAuB,GAC7C,KAAK,YAAY,KAAK,UAAW,GAEjC,EAAQ,GAAG,UAAU,CAAC,EAAQ,KAE5B,MACE,EAAc,IAAI,MAAM,mBAAmB,EAAQ,GACnD,EAAc,IAAI,MAAM,oBAAoB,GAE9C,KAAK,YAAY,KAAK,UAAW,EAAU,EAAU,GAEzD,CAEA,EAAA,CAAgB,EAAS,GAYvB,QAVG,IAAc,EAAQ,OAAO,UAE9B,EAAQ,OAAO,SAAe,MAAK,IACnC,EAAQ,OAAO,YAAe,GAI9B,EAAQ,OAAO,aAAe,EAG7B,eAAiB,EAAQ,QAAQ,WACpC,CACE,MAAM,EAAU,KAAK,MAAM,KAAK,YAAY,iBAAmB,KAC/D,EAAS,UAAU,aAAc,WAAa,GAC9C,KAAK,IAAI,IAAI,GAAG,EAAQ,OAAO,uBACjC,CACF,CAEA,EAAA,CAAiB,EAAU,EAAU,GAEnC,MAAM,EAAY,MAAK,EAAkB,GAEzC,KAAK,IAAI,IAAI,GAAG,cAEhB,MACE,EAAY,CAAC,EACb,EAAY,CAAC,EACb,EAAY,IAAI,IAAI,EAAS,IAAK,GAAG,OAAc,EAAS,QAAQ,QACpE,EAAY,EAAI,SAAS,QAAQ,OAAQ,IACzC,EAAY,MAAK,EAAY,EAAU,GACvC,EAAY,IAAI,gBAElB,OAAO,iBAAiB,EACxB,CAEE,UAAc,CAAE,UAAS,EAAM,cAAa,EAAM,MAAM,GAExD,KAAc,CAAE,UAAS,EAAM,cAAa,EAAM,MAAM,GAExD,OAAc,CAAE,YAAW,EAAM,MAAM,EAAS,QAChD,QAAc,CAAE,YAAW,EAAM,MAAM,EAAS,SAChD,IAAc,CAAE,YAAW,EAAM,MAAM,KAEzC,OAAO,iBAAiB,EACxB,CAEE,WAAc,CAAE,MAAM,GACtB,SAAc,CAAE,MAAM,GACtB,SAAc,CAAE,MAAM,KAGxB,OAAO,eAAe,EAAS,OAAQ,CAAE,YAAY,EAAM,MAAO,IAAI,KAAK,KAE3E,EAAS,OAAO,QAAU,IAAM,MAAK,EAAkB,GAEvD,EAAS,GAAG,UAAW,MAAK,EAAmB,KAAK,KAAM,IAC1D,EAAS,GAAG,QAAW,MAAK,EAAiB,KAAK,OAElD,EAAW,GAAG,QAAS,MAAK,EAAmB,KAAK,OACpD,EAAW,GAAG,QAAS,MAAK,EAAgB,KAAK,KAAM,IACvD,EAAW,GAAG,SAAS,IAAM,KAAK,IAAI,IAAI,GAAG,cAAsB,EAAQ,KAAK,UAAU,EAAQ,UAAU,EAAI,aAEhH,KAAK,aACL,KAAK,OAAO,SAAS,EAAS,GAC3B,MAAM,MAAK,EAA0B,KAAK,KAAM,IAChD,KAAK,MAAK,EAA2B,KAAK,KAAM,GACrD,CAEA,EAAA,CAAY,EAAU,GAEpB,OAAO,IAAI,SAAQ,CAAC,EAAQ,KAE1B,GAAG,EAAS,cACZ,CACE,MAAM,EAAQ,IAAI,MAAM,kCACxB,EAAM,KAAQ,8CACd,EAAO,EACT,KAEA,CACE,MACE,EAAY,GACZ,EAAa,GAAU,EAAK,KAAK,GAEnC,EAAS,GAAG,QAAS,GACrB,EAAS,GAAG,OAAQ,GACpB,EAAS,GAAG,OAAO,KAEjB,EAAS,IAAI,QAAS,GACtB,EAAS,IAAI,OAAQ,GAErB,EAAQ,KAAO,OAAO,OAAO,GAE7B,EAAO,EAAQ,KAAI,GAEvB,IAEJ,CAEA,EAAA,CAAkB,GAEhB,OAAO,EAAM,SAAS,IAAI,cAAc,SAAS,EAAG,IACtD,CAEA,EAAA,GAME,MAAO,GAHO,KAAK,MAAM,SAAS,OACpB,KAAK,SAAS,SAAS,IAAI,MAAM,EAAG,GAAG,SAAS,EAAG,OAE9B,aACrC,CAGA,EAAA,CAAkB,GAEhB,GAAG,EAAS,OACZ,CACE,MAAQ,GAAG,EAAU,SAAU,GAAG,IAAgB,EAAS,OAC3D,OAAO,EAAY,IAAM,MAAK,EAAkB,EAClD,CAEA,CACE,MAAM,SAAE,EAAQ,YAAE,GAAgB,EAAS,OAC3C,OAAO,EAAW,IAAM,MAAK,EAAkB,EACjD,CACF,CAEA,EAAA,CAAwB,GAEtB,KAAK,YAAe,MAAM,aAAa,GACvC,KAAK,YAAe,MAAM,mBAAmB,GAC7C,KAAK,QAAe,IAAI,aAAa,GAErC,MACE,EAAgB,MAAK,EAAsC,KAAK,MAChE,EAAgB,MAAK,EAAsC,KAAK,MAElE,KAAK,QAAQ,GAAG,mBAAoB,MAAK,EAAqB,KAAK,KAAM,EAAe,IACxF,KAAK,YAAY,GAAG,UAAW,MAAK,EAAgB,KAAK,OACzD,KAAK,YAAY,GAAG,UAAW,MAAK,EAAiB,KAAK,KAAM,UAChE,KAAK,YAAY,GAAG,UAAW,MAAK,EAAiB,KAAK,KAAM,SAClE,CAEA,EAAA,CAA2B,GAEzB,KAAK,YAAe,KAAK,aAAa,GACtC,KAAK,YAAe,MAAM,aAAa,GACvC,KAAK,QAAe,IAAI,aAAa,GAErC,MACE,EAAgB,MAAK,EAAgC,KAAK,MAC1D,EAAgB,MAAK,EAAgC,KAAK,MAE5D,KAAK,QAAQ,GAAG,aAAc,MAAK,EAAqB,KAAK,KAAM,EAAe,IAClF,KAAK,YAAY,GAAG,UAAW,MAAK,EAAgB,KAAK,OACzD,KAAK,YAAY,GAAG,UAAW,MAAK,EAAiB,KAAK,KAAM,SAChE,KAAK,YAAY,GAAG,UAAW,MAAK,EAAiB,KAAK,KAAM,QAClE,CAEA,EAAA,CAAsB,GAEpB,MAAM,EAAQ,IAAI,MAAM,uDACxB,EAAM,KAAQ,8BACd,EAAO,EACT,CAEA,EAAA,CAAgB,EAAS,GAEvB,MAAM,EAAQ,IAAI,MAAM,iBACxB,EAAM,KAAQ,8BACd,EAAM,MAAQ,EAEd,EAAQ,SAAS,MAAM,EACzB,CAEA,EAAA,CAAmB,GAEjB,MAAM,EAAQ,IAAI,MAAM,oBACxB,EAAM,KAAQ,iCACd,EAAQ,SAAS,MAAM,EACzB,CAEA,EAAA,CAA2B,GAEzB,KAAK,YACL,EAAQ,KAAK,SACf,CAEA,EAAA,CAAkB,GAEhB,KAAK,YACL,EAAQ,SAAS,OAAO,kBAAkB,MACxC,EAAQ,KAAK,aAAa,EAAQ,SAAS,OAAO,QAClD,EAAQ,KAAK,SACjB,CAEA,EAAA,CAA0B,EAAS,GAEjC,KAAK,aACL,EAAQ,KAAK,aAAa,EAAO,OACjC,KAAK,IAAI,IAAI,GAAG,GAClB,CAEA,EAAA,CAAmB,GAEjB,MAAM,EAAQ,IAAI,MAAM,oBACxB,EAAM,KAAQ,iCACd,EAAM,MAAQ,EACd,KAAK,IAAI,IAAI,GAAG,GAClB,CAEA,EAAA,CAAiB,GAEf,MAAM,EAAQ,IAAI,MAAM,kBACxB,EAAM,KAAQ,+BACd,EAAM,MAAQ,EACd,KAAK,IAAI,IAAI,GAAG,GAClB,CAEA,EAAA,CAAe,GAEb,MAAM,EAAQ,IAAI,MAAM,gBACxB,EAAM,KAAQ,sBACd,EAAM,MAAQ,EACd,KAAK,IAAI,IAAI,GAAG,GAClB","file":"/npm/@superhero/http-server@4.8.6/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@superhero/http-server@4.8.6/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import View           from '@superhero/http-server/view'\nimport Router         from '@superhero/router'\nimport Log            from '@superhero/log'\nimport NameGenerator  from '@superhero/id-name-generator'\nimport http           from 'node:http'\nimport https          from 'node:https'\nimport http2          from 'node:http2'\nimport net            from 'node:net'\nimport tls            from 'node:tls'\nimport { URL }        from 'node:url'\n\nexport function locate(locator)\n{\n  const router = new Router(locator)\n  return new HttpServer(router)\n}\n\nexport default class HttpServer\n{\n  // Name the server to easier be able to identify what logs \n  // belong to what server in a clustered environment.\n  name = new NameGenerator().generateName().toUpperCase()\n\n  // Tracks request statistics\n  // BigInt used for large numbers\n  dispatched  = 0n\n  completed   = 0n\n  abortions   = 0n\n  rejections  = 0n\n\n  // Internal server log\n  log = new Log({ label: `[HTTP:SERVER:${this.name}]` })\n\n  // TCP sockets\n  #sessions = new Set()\n\n  constructor(router)\n  {\n    this.router = router\n  }\n\n  async bootstrap(settings)\n  {\n    Object.assign(this.log.config, settings?.log)\n\n    const\n      routes         = settings?.router?.routes ?? {},\n      serverSettings = Object.assign({}, settings?.server)\n\n    this.router.setRoutes(routes, settings?.router?.seperators)\n\n    if(serverSettings.pfx\n    || serverSettings.key\n    || serverSettings.cert)\n    {\n      this.#bootstrapSecureServers(serverSettings)\n    }\n    else\n    {\n      this.#bootstrapNonSecureServers(serverSettings)\n    }\n\n    this.http2Server.on('session', this.addSession.bind(this))\n    this.gateway.on('close', () => setImmediate(() => this.log.info`closed`))\n    this.gateway.on('error', this.#onServerError.bind(this))\n  }\n\n  async listen(...args)\n  {\n    await new Promise((accept, reject) =>\n    {\n      if(this.gateway)\n      {\n        const\n          acceptCb = () => { this.gateway.off('error',     rejectCb); accept() },\n          rejectCb = () => { this.gateway.off('listening', acceptCb); reject() }\n\n        this.gateway.once('error',     rejectCb)\n        this.gateway.once('listening', acceptCb)\n\n        this.gateway.listen(...args)\n      }\n      else\n      {\n        this.#onServerNotAvailible(reject)\n      }\n    })\n\n    // Log the port the server is listening on.\n    const { port } = this.gateway.address()\n    this.log.info`port ${port} ⇡ listening`\n  }\n\n  async close()\n  {\n    // Close the gateway.\n    await new Promise((accept, reject) =>\n      this.gateway\n      ? this.gateway.close((error) =>\n          error\n          ? reject(error)\n          : setImmediate(accept))\n      : this.#onServerNotAvailible(reject))\n\n    // Close all sessions.\n    for(const session of this.#sessions)\n      await new Promise((accept) =>\n        session.closed\n        ? accept()\n        : session.close(accept))\n  }\n\n  addSession(session)\n  {\n    if(false === session.closed)\n    {\n      session.id = this.#composeSessionId()\n\n      session.on('close', () => this.log.info`${session.id} ⇣ closed`)\n      session.on('close', () => this.#sessions.delete(session))\n      session.on('error', (error) => this.log.fail`${error}`)\n      this.#sessions.add(session)\n      this.log.info`${session.id} ⇡ session`\n    }\n  }\n\n  // RFC 7540, Section 3.5\n  // The preface of a HTTP/2 request is designed to unambiguously signal \n  // that the client wants to use HTTP/2.\n  static #_HTTP2_PREFACE_BUFFER = Buffer.from('PRI * HTTP/2.0\\r\\n\\r\\nSM\\r\\n\\r\\n')\n\n  /**\n   * @param {net.Socket|tls.Socket} socket \n   * @returns {Buffer}\n   */\n  async #readPreface(socket)\n  {\n    let preface\n\n    do\n    {\n      if(socket.destroyed)\n      {\n        return Buffer.alloc(0)\n      }\n\n      if(preface = socket.read(HttpServer.#_HTTP2_PREFACE_BUFFER.length))\n      {\n        return preface\n      }\n\n      await new Promise((accept) => process.nextTick(accept))\n    }\n    while(null === preface)\n  }\n\n  #onGatewayConnection(onHttp1Socket, onHttp2Socket, socket)\n  {\n    socket.once('readable', async () => \n    {\n      const preface = await this.#readPreface(socket)\n\n      clearTimeout(timeout)\n      socket.unshift(preface)\n\n      preface.equals(HttpServer.#_HTTP2_PREFACE_BUFFER)\n      ? onHttp2Socket(socket)\n      : onHttp1Socket(socket)\n    })\n\n    const timeout = setTimeout(socket.destroy.bind(socket), 1e3)\n  }\n\n  #onGatewayConnectionHttp1Socket(socket)\n  {\n    this.http1Server.emit('connection', socket)\n  }\n\n  #onGatewayConnectionHttp2Socket(socket)\n  {\n    this.http2Server.emit('connection', socket)\n  }\n\n  #onGatewayConnectionSecureHttp1Socket(socket)\n  {\n    this.http1Server.emit('secureConnection', socket)\n  }\n\n  #onGatewayConnectionSecureHttp2Socket(socket)\n  {\n    // If possible to get this session some other way, then it should \n    // be concidered due to the version constraint.\n    // Added in: v21.7.0, v20.12.0.\n    const session = http2.performServerHandshake(socket)\n    this.http2Server.emit('session', session)\n\n    session.on('stream', (stream, headers) =>\n    {\n      const\n        upstream    = new http2.Http2ServerRequest(stream, headers),\n        downstream  = new http2.Http2ServerResponse(stream)\n\n      this.http2Server.emit('request', upstream, downstream)\n    })\n  }\n\n  #onHttp1Request(request, response)\n  {\n    if(undefined === request.socket.socketID)\n    {\n      request.socket.socketID     = this.#composeSessionId()\n      request.socket.socketIndex  = 1\n    }\n    else\n    {\n      request.socket.socketIndex += 1\n    }\n\n    if('keep-alive' === request.headers.connection)\n    {\n      const timeout = Math.floor(this.http1Server.keepAliveTimeout / 1e3)\n      response.setHeader('keep-alive', 'timeout=' + timeout)\n      this.log.info`${request.socket.socketID} ⇡ keep-alive`\n    }\n  }\n\n  #onServerRequest(protocol, upstream, downstream)\n  {\n    const requestID = this.#composeRequestId(upstream)\n\n    this.log.info`${requestID} ⇡ request`\n\n    const\n      session   = {},\n      request   = {},\n      url       = new URL(upstream.url, `${protocol}://${upstream.headers.host}`),\n      condition = url.pathname.replace(/\\/+$/, ''), // removed trailing slashes\n      body      = this.#bufferBody(upstream, request),\n      abortion  = new AbortController\n\n    Object.defineProperties(request, \n    {\n      // configurable and writable condition property\n      condition   : { writable:true, configurable:true, value:condition },\n      // configurable and writable stream data reader\n      body        : { writable:true, configurable:true, value:body },\n      // enumerable data readers, non-configurable \n      method      : { enumerable:true, value:upstream.method },\n      headers     : { enumerable:true, value:upstream.headers },\n      url         : { enumerable:true, value:url },\n    })\n    Object.defineProperties(session,\n    {\n      // non enumerable and non-configurable session properties\n      downstream  : { value:downstream },\n      upstream    : { value:upstream },\n      abortion    : { value:abortion },\n    })\n\n    Object.defineProperty(session, 'view', { enumerable: true, value: new View(session) })\n\n    abortion.signal.onabort = () => this.#onAbortedRequest(session)\n\n    upstream.on('aborted', this.#onUpstreamAborted.bind(this, session))\n    upstream.on('error',   this.#onUpstreamError.bind(this))\n\n    downstream.on('error', this.#onDownstreamError.bind(this))\n    downstream.on('close', this.#onStreamClosed.bind(this, session))\n    downstream.on('close', () => this.log.info`${requestID} ⇣ closed ${session.view.status} ${request.method} ${url.pathname}`)\n\n    this.dispatched++\n    this.router.dispatch(request, session)\n      .catch(this.#onRouterDispatchRejected.bind(this, session))\n      .then(this.#onRouterDispatchCompleted.bind(this, session))\n  }\n\n  #bufferBody(upstream, request)\n  {\n    return new Promise((accept, reject) =>\n    {\n      if(upstream.readableEnded)\n      {\n        const error = new Error('The upstream is already closed')\n        error.code  = 'E_HTTP_SERVER_READ_BUFFERED_UPSTREAM_CLOSED'\n        reject(error)\n      }\n      else\n      {\n        const\n          data      = [],\n          pushChunk = (chunk) => data.push(chunk)\n\n        upstream.on('error', reject)\n        upstream.on('data', pushChunk)\n        upstream.on('end', () => \n        {\n          upstream.off('error', reject)\n          upstream.off('data', pushChunk)\n\n          request.body = Buffer.concat(data)\n\n          accept(request.body)\n        })\n      }\n    })\n  }\n\n  #composeIdSegment(index)\n  {\n    return index.toString(36).toUpperCase().padStart(4, '0')\n  }\n\n  #composeSessionId()\n  {\n    const\n      timestamp = Date.now().toString(36),\n      randomKey = Math.random().toString(36).slice(2, 6).padStart(4, '0')\n\n    return `${timestamp}.${randomKey}`.toUpperCase()\n  }\n\n  // HTTP/2 streams have a unique ID, while HTTP/1.1 requests are identified by the socket.\n  #composeRequestId(upstream)\n  {\n    if(upstream.stream)\n    {\n      const { id:streamID, session:{ id:sessionID } } = upstream.stream\n      return sessionID + '.' + this.#composeIdSegment(streamID)\n    }\n    else\n    {\n      const { socketID, socketIndex } = upstream.socket\n      return socketID + '.' + this.#composeIdSegment(socketIndex)\n    }\n  }\n\n  #bootstrapSecureServers(serverSettings)\n  {\n    this.http1Server  = https.createServer(serverSettings)\n    this.http2Server  = http2.createSecureServer(serverSettings)\n    this.gateway      = tls.createServer(serverSettings)\n\n    const \n      onHttp1Socket = this.#onGatewayConnectionSecureHttp1Socket.bind(this),\n      onHttp2Socket = this.#onGatewayConnectionSecureHttp2Socket.bind(this)\n\n    this.gateway.on('secureConnection', this.#onGatewayConnection.bind(this, onHttp1Socket, onHttp2Socket))\n    this.http1Server.on('request', this.#onHttp1Request.bind(this))\n    this.http1Server.on('request', this.#onServerRequest.bind(this, 'https'))\n    this.http2Server.on('request', this.#onServerRequest.bind(this, 'https'))\n  }\n\n  #bootstrapNonSecureServers(serverSettings)\n  {\n    this.http1Server  = http.createServer(serverSettings)\n    this.http2Server  = http2.createServer(serverSettings)\n    this.gateway      = net.createServer(serverSettings)\n\n    const\n      onHttp1Socket = this.#onGatewayConnectionHttp1Socket.bind(this),\n      onHttp2Socket = this.#onGatewayConnectionHttp2Socket.bind(this)\n\n    this.gateway.on('connection', this.#onGatewayConnection.bind(this, onHttp1Socket, onHttp2Socket))\n    this.http1Server.on('request', this.#onHttp1Request.bind(this))\n    this.http1Server.on('request', this.#onServerRequest.bind(this, 'http'))\n    this.http2Server.on('request', this.#onServerRequest.bind(this, 'http'))\n  }\n\n  #onServerNotAvailible(reject)\n  {\n    const error = new Error('Server not availible (requires a bootstrap process)')\n    error.code  = 'E_HTTP_SERVER_NOT_AVAILIBLE'\n    reject(error)\n  }\n\n  #onStreamClosed(session, reason)\n  {\n    const error = new Error('Stream closed')\n    error.code  = 'E_HTTP_SERVER_STREAM_CLOSED'\n    error.cause = reason\n\n    session.abortion.abort(error)\n  }\n\n  #onUpstreamAborted(session)\n  {\n    const error = new Error('Upstream aborted')\n    error.code  = 'E_HTTP_SERVER_UPSTREAM_ABORTED'\n    session.abortion.abort(error)\n  }\n\n  #onRouterDispatchCompleted(session)\n  {\n    this.completed++\n    session.view.present()\n  }\n\n  #onAbortedRequest(session)\n  {\n    this.abortions++\n    session.abortion.signal.reason instanceof Error\n    ? session.view.presentError(session.abortion.signal.reason)\n    : session.view.present()\n  }\n\n  #onRouterDispatchRejected(session, reason)\n  {\n    this.rejections++\n    session.view.presentError(reason.cause)\n    this.log.fail`${reason}`\n  }\n\n  #onDownstreamError(reason)\n  {\n    const error = new Error('Downstream error')\n    error.code  = 'E_HTTP_SERVER_DOWNSTREAM_ERROR'\n    error.cause = reason\n    this.log.fail`${error}`\n  }\n\n  #onUpstreamError(reason)\n  {\n    const error = new Error('Upstream error')\n    error.code  = 'E_HTTP_SERVER_UPSTREAM_ERROR'\n    error.cause = reason\n    this.log.fail`${error}`\n  }\n\n  #onServerError(reason)\n  {\n    const error = new Error('Server error')\n    error.code  = 'E_HTTP_SERVER_ERROR'\n    error.cause = reason\n    this.log.fail`${error}`\n  }\n}"]}