medullah_web/http/
server.rs1use std::future::Future;
2
3use log::error;
4use ntex::web;
5
6use crate::app_setup::{
7 get_server_host_config, load_environment_variables, make_app_state, MedullahSetup,
8};
9use crate::env_logger::init_env_logger;
10use crate::http::kernel::{ntex_default_service, register_routes, setup_cors, setup_logger, Route};
11use crate::http::Method;
12use crate::prelude::{AppResult, MedullahState};
13
14pub struct ServerConfig<TB>
15where
16 TB: FnOnce() -> Vec<Route> + Send + Copy + 'static,
17{
18 pub app: String,
19 pub env_prefix: String,
20 pub private_key: String,
21 pub public_key: String,
22 pub auth_iss_public_key: String,
23
24 #[cfg(feature = "static")]
25 pub static_config: StaticFileConfig,
26
27 pub has_started_bootstrap: bool,
29
30 pub allowed_origins: Vec<String>,
32
33 pub allowed_methods: Vec<Method>,
35
36 pub boot_thread: TB,
37}
38
39#[cfg(feature = "static")]
40pub struct StaticFileConfig {
41 pub path: String,
42 pub dir: String,
43}
44
45pub fn init_bootstrap(service: &str) -> AppResult<()> {
46 load_environment_variables(service);
47 init_env_logger();
48 Ok(())
49}
50
51pub async fn start_ntex_server<Callback, Fut, TB>(
52 config: ServerConfig<TB>,
53 callback: Callback,
54) -> std::io::Result<()>
55where
56 Callback: FnOnce(MedullahState) -> Fut + Copy + Send + 'static,
57 Fut: Future<Output = AppResult<()>> + Send + 'static,
58 TB: FnOnce() -> Vec<Route> + Send + Copy + 'static,
59{
60 if !config.has_started_bootstrap {
61 init_bootstrap(&config.app).expect("failed to init bootstrap: ");
62 }
63
64 let app_state = make_app_state(MedullahSetup {
65 public_key: config.public_key,
66 private_key: config.private_key,
67 env_prefix: config.env_prefix.clone(),
68 auth_iss_public_key: config.auth_iss_public_key,
69 allowed_origins: config.allowed_origins,
70 allowed_methods: config.allowed_methods,
71 })
72 .await;
73
74 let (host, port, workers) = get_server_host_config(&config.env_prefix);
75
76 match callback(app_state.clone()).await {
77 Ok(_) => {}
78 Err(err) => {
79 error!("app bootstrap callback returned error: {:?}", err);
80 panic!("boostrap failed");
81 }
82 }
83
84 let boot = config.boot_thread;
85 web::HttpServer::new(move || {
86 let routes = boot();
87 let app = web::App::new()
88 .state(app_state.clone())
89 .configure(|cfg| register_routes(cfg, routes))
90 .wrap(setup_logger())
91 .wrap(
92 setup_cors(
93 app_state.allowed_origins.clone(),
94 app_state.allowed_methods.clone(),
95 )
96 .finish(),
97 )
98 .default_service(ntex_default_service());
99
100 if cfg!(feature = "static") {
101 #[cfg(feature = "static")]
102 {
103 return app.service(ntex_files::Files::new(
104 &config.static_config.path,
105 &config.static_config.dir,
106 ));
107 }
108 }
109
110 app
111 })
112 .bind((host, port))?
113 .workers(workers)
114 .run()
115 .await
116}