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