main.rs
⎇
Raw
1mod api;
2mod assets;
3mod auth;
4mod cli;
5mod db;
6mod error;
7
8use std::net::{IpAddr, SocketAddr};
9use std::sync::Arc;
10
11use anyhow::{bail, Context};
12use clap::Parser;
13use tower_http::trace::TraceLayer;
14
15use crate::cli::Cli;
16use crate::db::Db;
17use crate::error::AppState;
18
19#[tokio::main]
20async fn main() -> anyhow::Result<()> {
21 tracing_subscriber::fmt()
22 .with_env_filter(
23 tracing_subscriber::EnvFilter::try_from_default_env()
24 .unwrap_or_else(|_| "info,tower_http=warn".into()),
25 )
26 .init();
27
28 let cli = Cli::parse();
29
30 let root = cli
31 .root
32 .canonicalize()
33 .with_context(|| format!("cannot resolve root folder: {}", cli.root.display()))?;
34 if !root.is_dir() {
35 bail!("root folder is not a directory: {}", root.display());
36 }
37
38 let db = Db::open(&cli.db).await?;
39
40 let state = Arc::new(AppState {
41 db,
42 root: root.clone(),
43 https: cli.https,
44 });
45
46 let app = api::router(state).layer(TraceLayer::new_for_http());
47
48 let ip: IpAddr = cli.bind.parse().context("invalid --bind address")?;
49 let addr = SocketAddr::new(ip, cli.port);
50 let listener = tokio::net::TcpListener::bind(addr)
51 .await
52 .with_context(|| format!("cannot bind to {addr}"))?;
53
54 tracing::info!(root = %root.display(), "filebrowser-ng starting");
55 tracing::info!(addr = %addr, "listening (pass --bind 0.0.0.0 to expose beyond localhost)");
56 axum::serve(listener, app).await?;
57 Ok(())
58}
59