Files
evidencija-rezija/email-worker/src/routes/errorRouter.ts
Knee Cola 3e4d8fb95c refactor: rename email-server-worker to email-worker
Rename directory from email-server-worker to email-worker for clarity and brevity. Update all references in CLAUDE.md documentation.
2025-12-30 10:33:59 +01:00

81 lines
2.9 KiB
TypeScript

import { ErrorRequestHandler, Request, Response } from "express";
import createHttpError, { HttpError } from "http-errors";
import { createLogger } from '../lib/logger';
import { NgitLocals } from "../types/NgitLocals";
import { failedRequestCounter } from "../lib/metricsCounters";
import { SupportedRoutes } from "../types/enums/SupportedRoutes";
const consoleLog = createLogger("server:server");
/**
* Router koji se zadnji poziva, a koji sastavlja odgovor u slučaju greške
* @param err
* @param req
* @param res
* @param next
*/
export const errorRouter:ErrorRequestHandler = async (err:HttpError, req, res, next) => {
const requestPath = req.path as SupportedRoutes;
// kako je ovaj error handler dosta složen, moguće je da negdje baci grešku
// > zato je zamotan u try-catch
// > na taj način osiguravam da neće srušiti cijeli proces
try {
let { name:errorLogName, message:errorLogText } = err;
let responseBody:string = "";
switch(err.status) {
case 400:
responseBody = 'bad request';
break;
case 401:
responseBody = 'unauthorized';
break;
case 403:
responseBody = 'forbidden';
break;
case 404:
consoleLog(`page not found ${req.method} ${requestPath}`)
responseBody = 'page not found';
errorLogText = `page ${requestPath} not found`;
break;
case 500:
responseBody = "internal server error";
errorLogText = err.message;
break;
default:
responseBody = err.name;
errorLogText = `err.status=${err.status};err.name=${err.name};err.message=${err.message}`;
}
consoleLog(`${errorLogName}:${errorLogText}`);
// `headersSent` će biti TRUE ako je router kod kojeg se dogodila greška već poslao header-e
// > ako ih probam ponovo postaviti, to će baciti grešku ... a to ovdje mogu izbjeći
if(!res.headersSent) {
res.status(err.status);
res.setHeader('Content-Type', "text/html");
res.end(responseBody);
} else {
// AKO nije pozvan `end` - pozovi ga i završi obradu zahtjeva
// ... u suprotnom će konekcija ostati otvorena do timeout-a
if(!res.writableEnded) {
res.end();
}
}
} catch(ex:any) {
// ovu grešku će obraditi `finalErrorRouter`
next(createHttpError(500, ex));
}
// ne mogu dopustiti da prometheus client sruši server
try {
failedRequestCounter.inc({ path: requestPath, status: err.status });
(res.locals as NgitLocals).stopPrometheusTimer({ path: req.path, status: err.status });
} catch(ex:any) {
console.error(ex);
}
};