Skip to main content

foxtive_ntex/http/
kernel.rs

1use crate::enums::ResponseCode;
2use crate::http::Method;
3use crate::http::middlewares::{Middleware, MiddlewareChain};
4use crate::http::responder::Responder;
5use ntex::http::header;
6use ntex::web::ServiceConfig;
7use ntex::web::middleware::Logger;
8use ntex::{web, web::Route as NtexRoute};
9use ntex_cors::Cors;
10use tracing::info;
11
12pub struct Controller {
13    pub path: String,
14    pub handler: fn(cfg: &mut ServiceConfig),
15}
16
17pub struct Route {
18    pub prefix: String,
19    pub middlewares: Vec<Middleware>,
20    pub controllers: Vec<Controller>,
21}
22
23pub fn register_routes(config: &mut ServiceConfig, routes: Vec<Route>) {
24    tracing::debug!("discovering routes...");
25
26    for route in routes {
27        for controller in route.controllers {
28            let path = format!("{}{}", route.prefix, controller.path);
29            let display_path = if path.is_empty() { "/" } else { &path };
30            tracing::debug!("route group: {}", display_path);
31
32            let path_str = if path.is_empty() { "/" } else { &path };
33            let scope = web::scope(path_str);
34
35            if !route.middlewares.is_empty() {
36                config.service(
37                    scope
38                        .middleware(MiddlewareChain::new(route.middlewares.clone()))
39                        .configure(controller.handler)
40                );
41            } else {
42                config.service(scope.configure(controller.handler));
43            }
44        }
45    }
46
47    tracing::debug!("route discovery finished");
48}
49
50pub fn setup_logger() -> Logger {
51    Logger::default()
52        .exclude("/favicon.ico")
53        .exclude("/system/health-check")
54        .exclude("/api/v1/admin/health-check")
55}
56
57pub fn setup_cors(origins: Vec<String>, methods: Vec<Method>) -> Cors {
58    let mut cors = Cors::new();
59
60    // Handle wildcard separately from specific origins
61    let has_wildcard = origins.iter().any(|o| o == "*");
62
63    if has_wildcard {
64        info!("registering cors origin: '*' (wildcard)");
65        cors = cors.allowed_origin("*").send_wildcard();
66    } else {
67        for origin in origins {
68            info!("registering cors origin: '{}'", origin);
69            cors = cors.allowed_origin(&origin);
70        }
71    }
72
73    let allowed_methods = if methods.is_empty() {
74        vec![
75            Method::GET,
76            Method::POST,
77            Method::PUT,
78            Method::PATCH,
79            Method::DELETE,
80            Method::OPTIONS,
81        ]
82    } else {
83        methods
84    };
85
86    cors.allowed_methods(allowed_methods)
87        .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
88        .allowed_header(header::CONTENT_TYPE)
89        .max_age(3600)
90}
91
92pub fn ntex_default_service() -> NtexRoute {
93    web::to(|| async {
94        Responder::message("Requested Resource(s) Not Found", ResponseCode::NotFound)
95    })
96}