1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::future::Future;

use log::error;
use ntex::web;

use crate::app_setup::{
    get_server_host_config, load_environment_variables, make_app_state, MedullahSetup,
};
use crate::env_logger::init_env_logger;
use crate::http::kernel::{ntex_default_service, register_routes, setup_cors, setup_logger, Route};
use crate::prelude::{AppResult, MedullahState};

pub struct ServerConfig<TB>
where
    TB: FnOnce() -> Vec<Route> + Send + Copy + 'static,
{
    pub app: String,
    pub env_prefix: String,
    pub private_key: String,
    pub public_key: String,
    pub auth_iss_public_key: String,
    #[cfg(feature = "feat-static")]
    pub static_config: StaticFileConfig,
    pub boot_thread: TB,
}

#[cfg(feature = "feat-static")]
pub struct StaticFileConfig {
    pub path: String,
    pub dir: String,
}

pub async fn start_ntex_server<Callback, Fut, TB>(
    config: ServerConfig<TB>,
    callback: Callback,
) -> std::io::Result<()>
where
    Callback: FnOnce(MedullahState) -> Fut + Copy + Send + 'static,
    Fut: Future<Output = AppResult<()>> + Send + 'static,
    TB: FnOnce() -> Vec<Route> + Send + Copy + 'static,
{
    load_environment_variables(&config.app);

    init_env_logger();

    let app_state = make_app_state(MedullahSetup {
        public_key: config.public_key,
        private_key: config.private_key,
        env_prefix: config.env_prefix.clone(),
        auth_iss_public_key: config.auth_iss_public_key,
    })
    .await;

    let (host, port, workers) = get_server_host_config(&config.env_prefix);

    match callback(app_state.clone()).await {
        Ok(_) => {}
        Err(err) => {
            error!("app bootstrap callback returned error: {:?}", err);
            panic!("boostrap failed");
        }
    }

    let boot = config.boot_thread;
    web::HttpServer::new(move || {
        let routes = boot();
        let app = web::App::new()
            .state(app_state.clone())
            .configure(|cfg| register_routes(cfg, routes))
            .wrap(setup_logger())
            .wrap(setup_cors(app_state.allowed_origins.clone()).finish())
            .default_service(ntex_default_service());

        if cfg!(feature = "feat-static") {
            #[cfg(feature = "feat-static")]
            {
                return app.service(ntex_files::Files::new(
                    &config.static_config.path,
                    &config.static_config.dir,
                ));
            }
        }

        app
    })
    .bind((host, port))?
    .workers(workers)
    .run()
    .await
}