summaryrefslogtreecommitdiff
path: root/src/web/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/web/mod.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/web/mod.rs b/src/web/mod.rs
new file mode 100644
index 0000000..530a3f9
--- /dev/null
+++ b/src/web/mod.rs
@@ -0,0 +1,82 @@
+use std::net::{IpAddr, SocketAddr, TcpListener};
+use std::time::Duration;
+
+use axum::routing::get;
+use axum::{Extension, Router};
+use moka::future::Cache;
+use tokio::task::JoinHandle;
+use tower_cookies::CookieManagerLayer;
+use tracing::{error, info};
+
+use crate::config::Config;
+use crate::database::Database;
+use crate::Result;
+
+mod api;
+mod extract;
+mod file;
+mod http;
+mod pages;
+
+pub struct WebServer {
+ config: Config,
+ database: Database,
+ addr: SocketAddr,
+}
+
+impl WebServer {
+ pub async fn new(config: Config, database: Database) -> Result<Self> {
+ let addr = format!("[::]:{}", config.web_port).parse::<SocketAddr>()?;
+ Ok(Self {
+ config,
+ database,
+ addr,
+ })
+ }
+
+ pub async fn run(&self) -> Result<JoinHandle<()>> {
+ let config = self.config.clone();
+ let database = self.database.clone();
+ let listener = TcpListener::bind(self.addr)?;
+
+ info!(
+ "Listening for HTTP traffic on [::]:{}",
+ self.config.web_port
+ );
+
+ let app = Self::router(config, database);
+ let server = axum::Server::from_tcp(listener)?;
+
+ let web_handle = tokio::spawn(async move {
+ if let Err(err) = server
+ .serve(app.into_make_service_with_connect_info::<SocketAddr>())
+ .await
+ {
+ error!("{err}");
+ }
+ });
+
+ Ok(web_handle)
+ }
+
+ fn router(config: Config, database: Database) -> Router {
+ let cache: Cache<String, IpAddr> = Cache::builder()
+ .time_to_live(Duration::from_secs(60 * 15))
+ .max_capacity(config.dns_cache_size)
+ .build();
+
+ Router::new()
+ .nest("/", pages::router())
+ .nest("/api", api::router())
+ .layer(Extension(config))
+ .layer(Extension(cache))
+ .layer(Extension(database))
+ .layer(CookieManagerLayer::new())
+ .route("/js/*path", get(file::js))
+ .route("/css/*path", get(file::css))
+ .route("/fonts/*path", get(file::fonts))
+ .route("/image/*path", get(file::image))
+ .route("/favicon.ico", get(file::favicon))
+ .route("/robots.txt", get(file::robots))
+ }
+}