diff options
Diffstat (limited to '')
-rw-r--r-- | src/web/mod.rs | 82 |
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)) + } +} |