headless_lms_server/programs/
start_server.rs1use crate::{
2 config::{self, ServerConfigBuilder},
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 dotenv::dotenv;
16use listenfd::ListenFd;
17use rustls::crypto::ring;
18use std::env;
19
20pub async fn main() -> anyhow::Result<()> {
22 dotenv().ok();
23 setup_tracing()?;
24
25 ring::default_provider()
27 .install_default()
28 .expect("failed to install rustls ring crypto provider");
29
30 let private_cookie_key =
32 env::var("PRIVATE_COOKIE_KEY").expect("PRIVATE_COOKIE_KEY must be defined");
33 let test_mode = env::var("TEST_MODE").is_ok();
34 let allow_no_https_for_development = env::var("ALLOW_NO_HTTPS_FOR_DEVELOPMENT").is_ok();
35
36 if test_mode {
37 info!("***********************************");
38 info!("* Starting backend in test mode *");
39 info!("***********************************");
40 }
41 let server_config = ServerConfigBuilder::try_from_env()
42 .expect("Failed to create server config builder")
43 .build()
44 .await
45 .expect("Failed to create server config");
46 let mut server = HttpServer::new(move || {
47 let server_config = server_config.clone();
48 App::new()
49 .configure(move |config| config::configure(config, server_config))
50 .wrap(
51 SessionMiddleware::builder(
52 CookieSessionStore::default(),
53 Key::from(private_cookie_key.as_bytes()),
54 )
55 .cookie_name("session".to_string())
56 .cookie_secure(!allow_no_https_for_development)
57 .cookie_same_site(SameSite::Strict) .cookie_http_only(true) .cookie_path("/api".to_string()) .cookie_content_security(CookieContentSecurity::Private)
61 .session_lifecycle(SessionLifecycle::PersistentSession(
62 PersistentSession::default()
63 .session_ttl(actix_web::cookie::time::Duration::days(100))
64 .session_ttl_extension_policy(TtlExtensionPolicy::OnEveryRequest),
65 ))
66 .build(),
67 )
68 .wrap(Logger::new(
69 "Completed %r %s %b bytes - %D ms, request_id=%{request-id}o",
70 ))
71 });
72
73 let mut listenfd = ListenFd::from_env();
75 server = match listenfd.take_tcp_listener(0)? {
76 Some(listener) => server.listen(listener)?,
77 None => {
78 let host = env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
79 let port = env::var("PORT").unwrap_or_else(|_| "3001".to_string());
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}