💾 Archived View for iich.space › src › modules › gemini › server.ts captured on 2021-12-17 at 13:26:06.

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

import {
  TlsOptions,
  Server as TlsServer,
  createServer as tlsCreateServer,
} from 'tls';

import { createLogger } from '@/log';

import { Request } from './request';
import { Response } from './response';
import { Status } from './status';

type Handler = (req: Request, res: Response) => Promise<void> | void;

export declare interface Server {
  on(event: 'request', listener: Handler): this;
}

const log = createLogger();

export const createServer = (
  options: TlsOptions,
  handler?: Handler,
): TlsServer & Server => {
  const server = tlsCreateServer(
    {
      allowHalfOpen: true,
      rejectUnauthorized: false,
      requestCert: true,
      ...options,
    },
    async (socket) => {
      log.debug('socket connected');

      const response = Response.fromSocket(socket);

      let request: Request;

      try {
        request = await Request.fromSocket(socket);

        if (handler !== undefined) {
          handler(request, response);
        }
      } catch (error: unknown) {
        log.error(error);

        try {
          response.sendStatus(
            Status.PERMANENT_FAILURE,
            error instanceof Error ? error.toString() : '',
          );
          response.end();
        } catch (error: unknown) {
          log.error(error);
        }

        return;
      }

      server.emit('request', request, response);
    },
  );

  server.on('tlsClientError', (error) => {
    log.error(error.toString());
  });

  server.on('listening', () => {
    let address = '';

    const serverAddress = server.address();

    if (serverAddress !== null) {
      if (typeof serverAddress === 'string') {
        address = serverAddress;
      } else {
        address = `${serverAddress.address}:${serverAddress.port}`;
      }
    }

    log.info(`listening on ${address}`);
  });

  return server;
};

process.on('uncaughtException', (error) => {
  log.error(error);
});