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