https#createServer TypeScript Examples

The following examples show how to use https#createServer. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: https.ts    From farrow with MIT License 4 votes vote down vote up
createHttpsPipeline = (options?: HttpsPipelineOptions): HttpsPipeline => {
  const isNotProduction = process.env.NODE_ENV !== 'production'
  const config: HttpsPipelineOptions = {
    logger: isNotProduction,
    errorStack: isNotProduction,
    ...options,
  }

  const loggerOptions: LoggerOptions = !config.logger || typeof config.logger === 'boolean' ? {} : config.logger

  const logger = config.logger ? createLogger(loggerOptions) : null

  const router = Router()

  const handleRequest: HttpsPipeline['handle'] = (req, res, options) => {
    if (typeof req.url !== 'string') {
      throw new Error(`req.url is not existed`)
    }

    const { url } = req

    const [pathname = '/', search = ''] = url.split('?')

    const method = req.method ?? 'GET'

    const query = (req as any).query ?? (parseQuery(search, config.query) as RequestQuery)

    const headers = req.headers as RequestHeaders

    const cookies = parseCookies(req.headers['cookie'] ?? '', config.cookie) as RequestCookies

    const handleBody = (body: any) => {
      const { basename, requestInfo } = handleBasenames(config.basenames ?? [], {
        pathname,
        method,
        query,
        body,
        headers,
        cookies,
      })

      const storages = config.contexts?.({
        req,
        requestInfo,
        basename,
      })

      const container = createContainer({
        ...storages,
        request: RequestContext.create(req),
        response: ResponseContext.create(res),
        basenames: BasenamesContext.create([basename]),
        requestInfo: RequestInfoContext.create(requestInfo),
      })

      const maybeAsyncResponse = router.run(requestInfo, {
        container,
        onLast: () => {
          if (options?.onLast) {
            return Response.custom(options.onLast)
          }
          return NOT_FOUND_RESPONSE
        },
      })

      if (isPromise(maybeAsyncResponse)) {
        return maybeAsyncResponse.then((response) =>
          handleResponse({
            req,
            res,
            requestInfo,
            responseInfo: response.info,
            container,
          }),
        )
      }
      return handleResponse({
        req,
        res,
        requestInfo,
        responseInfo: maybeAsyncResponse.info,
        container,
      })
    }

    if ((req as any).body) {
      return handleBody((req as any).body)
    }
    const maybeAsyncBody = getBody(req, config.body)
    if (maybeAsyncBody) {
      return maybeAsyncBody
        .then((body) => handleBody(body))
        .catch((err) => {
          throw err
        })
    }
    return handleBody(maybeAsyncBody)
  }

  const handle: HttpsPipeline['handle'] = (req, res, options) => {
    if (logger) {
      const startTime = Date.now()
      const method = req.method ?? 'GET'
      const url = req.url ?? ''

      let contentLength = 0

      let hasLogOut = false
      const logOutput = (event: LoggerEvent) => {
        if (hasLogOut) return
        hasLogOut = true
        logger?.logOutput(method, url, res.statusCode, startTime, contentLength || getContentLength(res), event)
      }

      logger.logInput(method, url)
      // log close
      res.once('close', () => {
        logOutput('close')
      })

      // log error
      res.once('error', () => {
        logOutput('error')
      })

      // log finish
      res.once('finish', () => {
        logOutput('finish')
      })

      // log stream pipe response
      res.once('pipe', (readable) => {
        readable.on('data', (chunk) => {
          contentLength += chunk.length
        })
      })
    }

    try {
      return handleRequest(req, res, options)
    } catch (error: any) {
      const message = (config.errorStack ? error?.stack || error?.message : error?.message) ?? ''

      if (!res.headersSent) {
        res.statusCode = error.statusCode ?? 500
        res.setHeader('Content-Type', 'text/plain')
        res.setHeader('Content-Length', Buffer.byteLength(message))
      }

      if (!res.writableEnded) {
        res.end(Buffer.from(message))
      }
    }
  }

  const server: HttpsPipeline['server'] = () => {
    return options?.tls ? createServer(options.tls, handle) : createServer(handle)
  }

  const listen: HttpsPipeline['listen'] = (...args) => {
    return server().listen(...args)
  }

  return {
    ...router,
    handle,
    listen,
    server,
  }
}
Example #2
Source File: runForwardingServer.ts    From shroom with GNU Lesser General Public License v3.0 4 votes vote down vote up
export function runForwardingServer({
  wsPort,
  targetPort,
  debug = false,
  prependLengthPrefix = false,
  targetHost,
  keyPath,
  certPath
}: {
  wsPort: number;
  targetPort: number;
  debug?: boolean;
  targetHost?: string;
  prependLengthPrefix?: boolean;
  keyPath?: string,
  certPath?: string,
}) {
  let webSocketOptions: WebSocket.ServerOptions;
  if (keyPath && certPath) {
    webSocketOptions = {
      server: createServer({
        key: readFileSync(keyPath),
        cert: readFileSync(certPath)
      })
    };

    webSocketOptions.server?.listen(wsPort);
  } else {
    webSocketOptions = {
      port: wsPort
    };
  }

  const server = new WebSocket.Server(webSocketOptions);

  const targetHostStr =
    targetHost == null ? `:${targetPort}` : `${targetHost}:${targetPort}`;
  console.log(
    `${webSocketOptions.server ? 'Secure' : ''} WebSocket Server started on port ${wsPort}. Forwarding traffic to ${targetHostStr}.`
  );

  let idCounter = 0;

  server.on("connection", (ws) => {
    const id = ++idCounter;

    if (debug) console.log(`[${id}] Forwarding WebSocket Client connection`);

    // When a websocket client connects, create a socket to the emulator server
    const connection = createConnection({ port: targetPort, host: targetHost });

    // Pipe to the frame-stream decoder to handle length prefixed messages
    connection.pipe(frame.decode()).on("data", (buffer: Buffer) => {
      if (prependLengthPrefix) {
        const framedBuffer: any = buffer;

        const baseBuffer = new ByteBuffer();
        baseBuffer.writeInt(framedBuffer.frameLength);
        baseBuffer.append(buffer);

        ws.send(baseBuffer.flip().toBuffer());
      } else {
        ws.send(buffer);
      }

      if (debug) console.log(`[${id}] Server => Client:`, buffer);
    });

    // Forward close event from server to websocket client
    connection.on("close", () => {
      ws.close();
      if (debug) console.log(`[${id}] Server closed the connection`);
    });

    // Forward messages sent by the websocket client to the emulator server
    ws.on("message", (message) => {
      const buffer = message as Buffer;
      const data = new ByteBuffer();

      // Write an int to the payload with the size of the buffer we are sending
      data.writeInt(buffer.length);
      data.append(buffer);

      const sendBuffer = data.flip().toBuffer();
      connection.write(sendBuffer);

      if (debug) console.log(`[${id}] Client => Server:`, sendBuffer);
    });

    // Forward close event to the emulator server
    ws.on("close", () => {
      connection.end();
      if (debug) console.log(`[${id}] WebSocket closed the connection`);
    });
  });

  return {
    close() {
      server.close();
    },
  };
}