| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- import { HTTPStatus } from 'deps';
- import { isSuccessfulStatus } from 'deps';
- import { Logger, logger as defaultLogger } from 'infra/logger.ts';
- export interface ControllerOptions {
- status?: HTTPStatus;
- json?: boolean;
- }
- export type ControllerHandler = (
- req: Request,
- error?: string,
- headers?: Record<string, string>,
- ) => Response | Promise<Response>;
- export type ControllerHandlers = Record<string, ControllerHandler>;
- export default class Controller {
- constructor(
- private handlers: ControllerHandlers = {},
- private logger: Logger = defaultLogger,
- ) {}
- public setHandlers(handlers: ControllerHandlers): void {
- this.handlers = handlers;
- }
- public setHandler(
- path: string,
- method: string,
- handler: ControllerHandler,
- ): void {
- this.handlers[`${path}_${method}`] = handler;
- }
- public getHandlers(): ControllerHandlers {
- return this.handlers;
- }
- public getHandler(path: string, method: string): ControllerHandler {
- return this.handlers[`${path}_${method}`];
- }
- public hasHandler(path: string, method: string): boolean {
- return `${path}_${method}` in this.handlers;
- }
- public response = (
- req: Request,
- body: string,
- options: ControllerOptions = {},
- ) => {
- const url = new URL(req.url);
- const output = new TextEncoder().encode(body);
- const response = new Response(output, {
- status: options.status ?? HTTPStatus.OK,
- });
- const userName = Controller.getUser(req);
- if (options.json) {
- response.headers.set('Content-Type', 'application/json');
- }
- const userAgent = req.headers.get('User-Agent') ?? '-';
- const logMessage = Controller.getLogMessage(
- req.method,
- url.pathname,
- response.status,
- output.byteLength,
- userAgent,
- userName,
- );
- if (isSuccessfulStatus(response.status)) {
- if (Controller.isHealthCheck(userAgent)) {
- this.logger.debug(logMessage);
- } else {
- this.logger.info(logMessage);
- }
- } else {
- this.logger.error(logMessage);
- }
- return response;
- };
- public responseJSON = (
- req: Request,
- body: Record<string, unknown>,
- options: ControllerOptions = {},
- ) => {
- options.json = true;
- return this.response(req, JSON.stringify(body), options);
- };
- private static getUser = (req: Request): string | undefined => {
- const authHeader = req.headers.get('Authorization');
- if (authHeader && authHeader.startsWith('Basic ')) {
- const base64Credentials = authHeader.slice(6);
- const credentials = atob(base64Credentials);
- const [userName] = credentials.split(':');
- return userName;
- }
- return;
- };
- private static getLogMessage(
- method: string,
- path: string,
- status: number,
- length: number,
- userAgent: string,
- userName?: string,
- ) {
- const user = userName ? userName + ' ' : '';
- return `${method} ${path} ${user}${status} ${length} (${userAgent})`;
- }
- private static isHealthCheck(userAgent: string): boolean {
- return userAgent === Deno.env.get('DOCKER_USER_AGENT');
- }
- }
|