#!/usr/bin/env python3 # -*- coding: utf-8 -*- from typing import Self, Any, Sequence from re import Match as REMatch from mimetypes import guess_type as get_mime_by_extension from Interfaces.Application.NucelarMonitorInterface import NucelarMonitorInterface from Models.RouteModel import RouteModel from Models.ResponseModel import ResponseModel from Models.RequestModel import RequestModel class RoutesManager: def __init__(self:Self, nucelar_monitor:NucelarMonitorInterface) -> None: self.nucelar_monitor:NucelarMonitorInterface = nucelar_monitor key:str self.__routes:list[RouteModel] = [] for key in ( "default_routes_files", "routes_files", "default_routes", "routes" ): self.add(self.nucelar_monitor.settings.get(key, None, []), True) def add(self:Self, inputs:Any|None, overwrite:bool = False) -> None: route:str|Sequence[str|list[str]|RouteModel] for route in self.nucelar_monitor.files.load_json(inputs, False): item:RouteModel = route if isinstance(route, RouteModel) else RouteModel(self.nucelar_monitor, route) if item.error: self.add(route, overwrite) continue exists:RouteModel done:bool = False for exists in self.__routes: if exists.method == item.method and exists.route == item.route: if overwrite: done = True self.__routes.remove(exists) else: break if not done: self.__routes.append(item) def get(self:Self, request:RequestModel, response:ResponseModel) -> None: route:RouteModel for route in self.__routes: if route.method != request.method: continue matches:REMatch[str]|None = route.route.match(request.request) if not matches: continue request.set_uri_variables(route.variables, matches) if route.action: try: route.action(request, response) except Exception as exception: response.build({ "ok" : False, "code" : 500, "message" : "Internal server error", "error" : str(exception) }, "application/json", 500, "Internal server error") self.nucelar_monitor.exception(exception, "nucelar_monitor_routes_manager_get_exception", { "request" : request.request, "method" : request.method }) return if route.path: index:str for index in request.index_files: full_path = route.path + request.request + ("" if index == "" else "/" + index) if (response_data := self.nucelar_monitor.files.load_file(full_path, "rb")) is not None: response.set_data( response_data, get_mime_by_extension(full_path)[0] or "application/octet-stream" ) return response.build({ "ok" : False, "code" : 404, "message" : "Not found" }, "application/json", 404, "Not found")