]> Untitled Git - lemmy.git/blob - src/main.rs
Merge remote-tracking branch 'yerba/main' into main
[lemmy.git] / src / main.rs
1 #[macro_use]
2 extern crate diesel_migrations;
3
4 use actix::prelude::*;
5 use actix_web::{
6   body::Body,
7   dev::{Service, ServiceRequest, ServiceResponse},
8   http::{
9     header::{CACHE_CONTROL, CONTENT_TYPE},
10     HeaderValue,
11   },
12   *,
13 };
14 use diesel::{
15   r2d2::{ConnectionManager, Pool},
16   PgConnection,
17 };
18 use lazy_static::lazy_static;
19 use lemmy_api::match_websocket_operation;
20 use lemmy_apub::activity_queue::create_activity_queue;
21 use lemmy_db::get_database_url_from_env;
22 use lemmy_rate_limit::{rate_limiter::RateLimiter, RateLimit};
23 use lemmy_server::{code_migrations::run_advanced_migrations, routes::*};
24 use lemmy_structs::blocking;
25 use lemmy_utils::{settings::Settings, LemmyError, CACHE_CONTROL_REGEX};
26 use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
27 use reqwest::Client;
28 use std::sync::Arc;
29 use tokio::sync::Mutex;
30
31 lazy_static! {
32   // static ref CACHE_CONTROL_VALUE: String = format!("public, max-age={}", 365 * 24 * 60 * 60);
33   // Test out 1 hour here, this is breaking some things
34   static ref CACHE_CONTROL_VALUE: String = format!("public, max-age={}", 60 * 60);
35 }
36
37 embed_migrations!();
38
39 #[actix_web::main]
40 async fn main() -> Result<(), LemmyError> {
41   env_logger::init();
42   let settings = Settings::get();
43
44   // Set up the r2d2 connection pool
45   let db_url = match get_database_url_from_env() {
46     Ok(url) => url,
47     Err(_) => settings.get_database_url(),
48   };
49   let manager = ConnectionManager::<PgConnection>::new(&db_url);
50   let pool = Pool::builder()
51     .max_size(settings.database.pool_size)
52     .build(manager)
53     .unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
54
55   // Run the migrations from code
56   blocking(&pool, move |conn| {
57     embedded_migrations::run(conn)?;
58     run_advanced_migrations(conn)?;
59     Ok(()) as Result<(), LemmyError>
60   })
61   .await??;
62
63   // Set up the rate limiter
64   let rate_limiter = RateLimit {
65     rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
66   };
67
68   println!(
69     "Starting http server at {}:{}",
70     settings.bind, settings.port
71   );
72
73   let activity_queue = create_activity_queue();
74   let chat_server = ChatServer::startup(
75     pool.clone(),
76     rate_limiter.clone(),
77     |c, i, o, d| Box::pin(match_websocket_operation(c, i, o, d)),
78     Client::default(),
79     activity_queue.clone(),
80   )
81   .start();
82
83   // Create Http server with websocket support
84   HttpServer::new(move || {
85     let context = LemmyContext::create(
86       pool.clone(),
87       chat_server.to_owned(),
88       Client::default(),
89       activity_queue.to_owned(),
90     );
91     let rate_limiter = rate_limiter.clone();
92     App::new()
93       .wrap_fn(add_cache_headers)
94       .wrap(middleware::Logger::default())
95       .data(context)
96       // The routes
97       .configure(|cfg| api::config(cfg, &rate_limiter))
98       .configure(federation::config)
99       .configure(feeds::config)
100       .configure(|cfg| images::config(cfg, &rate_limiter))
101       .configure(nodeinfo::config)
102       .configure(webfinger::config)
103       .service(actix_files::Files::new("/docs", "/app/documentation"))
104   })
105   .bind((settings.bind, settings.port))?
106   .run()
107   .await?;
108
109   Ok(())
110 }
111
112 fn add_cache_headers<S>(
113   req: ServiceRequest,
114   srv: &mut S,
115 ) -> impl Future<Output = Result<ServiceResponse, Error>>
116 where
117   S: Service<Request = ServiceRequest, Response = ServiceResponse<Body>, Error = Error>,
118 {
119   let fut = srv.call(req);
120   async move {
121     let mut res = fut.await?;
122     if let Some(content_type) = res.headers().get(CONTENT_TYPE) {
123       if CACHE_CONTROL_REGEX.is_match(content_type.to_str().unwrap()) {
124         let header_val = HeaderValue::from_static(&CACHE_CONTROL_VALUE);
125         res.headers_mut().insert(CACHE_CONTROL, header_val);
126       }
127     }
128     Ok(res)
129   }
130 }