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