headless_lms_server/programs/
start_server.rs1use crate::{
2 config::{self, ServerConfigBuilder, ServerRuntimeConfig, set_server_runtime_config},
3 setup_tracing,
4};
5use actix_session::{
6 SessionMiddleware,
7 config::{CookieContentSecurity, PersistentSession, SessionLifecycle, TtlExtensionPolicy},
8 storage::CookieSessionStore,
9};
10use actix_web::{
11 App, HttpServer,
12 cookie::{Key, SameSite},
13 middleware::Logger,
14};
15use dotenvy::dotenv;
16use listenfd::ListenFd;
17use rustls::crypto::ring;
18
19pub async fn main() -> anyhow::Result<()> {
21 dotenv().ok();
22 setup_tracing()?;
23
24 ring::default_provider()
26 .install_default()
27 .expect("failed to install rustls ring crypto provider");
28
29 let runtime_config = ServerRuntimeConfig::try_from_env()?;
30 let private_cookie_key = runtime_config.private_cookie_key.clone();
31 let test_mode = runtime_config.test_mode;
32 let allow_no_https_for_development = runtime_config.allow_no_https_for_development;
33 let host = runtime_config.host.clone();
34 let port = runtime_config.port.clone();
35 set_server_runtime_config(runtime_config.clone())?;
36
37 if test_mode {
38 info!("***********************************");
39 info!("* Starting backend in test mode *");
40 info!("***********************************");
41 }
42 let server_config = ServerConfigBuilder::from_runtime_config(&runtime_config)
43 .await
44 .expect("Failed to create server config builder from runtime config")
45 .build()
46 .await
47 .expect("Failed to create server config");
48 let mut server = HttpServer::new(move || {
49 let server_config = server_config.clone();
50 App::new()
51 .configure(move |config| config::configure(config, server_config))
52 .wrap(
53 SessionMiddleware::builder(
54 CookieSessionStore::default(),
55 Key::from(private_cookie_key.as_bytes()),
56 )
57 .cookie_name("session".to_string())
58 .cookie_secure(!allow_no_https_for_development)
59 .cookie_same_site(SameSite::Strict) .cookie_http_only(true) .cookie_path("/api".to_string()) .cookie_content_security(CookieContentSecurity::Private)
63 .session_lifecycle(SessionLifecycle::PersistentSession(
64 PersistentSession::default()
65 .session_ttl(actix_web::cookie::time::Duration::days(100))
66 .session_ttl_extension_policy(TtlExtensionPolicy::OnEveryRequest),
67 ))
68 .build(),
69 )
70 .wrap(Logger::new(
71 "Completed %r %s %b bytes - %D ms, request_id=%{request-id}o",
72 ))
73 });
74
75 let mut listenfd = ListenFd::from_env();
77 server = match listenfd.take_tcp_listener(0)? {
78 Some(listener) => server.listen(listener)?,
79 None => {
80 let bind_address = format!("{}:{}", host, port);
81 info!("Binding to address: {}", bind_address);
82 server.bind(bind_address)?
83 }
84 };
85
86 info!("Starting server.");
87 server.run().await?;
88
89 Ok(())
90}