diff options
author | Sven-Hendrik Haase <svenstaro@gmail.com> | 2025-03-07 11:38:10 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-07 11:38:10 +0000 |
commit | 419204c291273e073cb4e1049655bea848dbc441 (patch) | |
tree | 341cb7ac4bd5915deb8fe58947b3cc352687556d /src/main.rs | |
parent | Reformat style.scss (diff) | |
parent | Add asynchronous directory size counting (diff) | |
download | miniserve-419204c291273e073cb4e1049655bea848dbc441.tar.gz miniserve-419204c291273e073cb4e1049655bea848dbc441.zip |
Merge pull request #1482 from svenstaro/add-asynchronous-directory-size-loading
Add asynchronous directory size counting
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/src/main.rs b/src/main.rs index 856d22d..adda3f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ use actix_web::{ }; use actix_web_httpauth::middleware::HttpAuthentication; use anyhow::Result; +use bytesize::ByteSize; use clap::{CommandFactory, Parser, crate_version}; use colored::*; use dav_server::{ @@ -21,7 +22,8 @@ use dav_server::{ actix::{DavRequest, DavResponse}, }; use fast_qr::QRBuilder; -use log::{error, warn}; +use log::{error, info, warn}; +use serde::Deserialize; mod archive; mod args; @@ -38,6 +40,7 @@ mod webdav_fs; use crate::config::MiniserveConfig; use crate::errors::{RuntimeError, StartupError}; +use crate::file_op::recursive_dir_size; use crate::webdav_fs::RestrictedFs; static STYLESHEET: &str = grass::include!("data/style.scss"); @@ -215,7 +218,7 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), StartupError> { let srv = actix_web::HttpServer::new(move || { App::new() .wrap(configure_header(&inside_config.clone())) - .app_data(inside_config.clone()) + .app_data(web::Data::new(inside_config.clone())) .app_data(stylesheet.clone()) .wrap(from_fn(errors::error_page_middleware)) .wrap(middleware::Logger::default()) @@ -224,6 +227,7 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), StartupError> { middleware::Compress::default(), )) .route(&inside_config.healthcheck_route, web::get().to(healthcheck)) + .route(&inside_config.api_route, web::post().to(api)) .route(&inside_config.favicon_route, web::get().to(favicon)) .route(&inside_config.css_route, web::get().to(css)) .service( @@ -353,7 +357,7 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) { files = files.default_handler(fn_service(|req: ServiceRequest| async { let (req, _) = req.into_parts(); let conf = req - .app_data::<MiniserveConfig>() + .app_data::<web::Data<MiniserveConfig>>() .expect("Could not get miniserve config"); let mut path_base = req.path()[1..].to_string(); if path_base.ends_with('/') { @@ -438,6 +442,41 @@ async fn healthcheck() -> impl Responder { HttpResponse::Ok().body("OK") } +#[derive(Deserialize, Debug)] +enum ApiCommand { + /// Request the size of a particular directory + DirSize(String), +} + +/// This "API" is pretty shitty but frankly miniserve doesn't really need a very fancy API. Or at +/// least I hope so. +async fn api( + command: web::Json<ApiCommand>, + config: web::Data<MiniserveConfig>, +) -> Result<impl Responder, RuntimeError> { + match command.into_inner() { + ApiCommand::DirSize(dir) => { + // Convert the relative dir to an absolute path on the system + let sanitized_path = + file_utils::sanitize_path(&dir, true).expect("Expected a path to directory"); + let full_path = config + .path + .canonicalize() + .expect("Couldn't canonicalize path") + .join(sanitized_path); + info!("Requested directory listing for {full_path:?}"); + + let dir_size = recursive_dir_size(&full_path).await?; + if config.show_exact_bytes { + Ok(format!("{dir_size} B")) + } else { + let dir_size = ByteSize::b(dir_size); + Ok(dir_size.to_string()) + } + } + } +} + async fn favicon() -> impl Responder { let logo = include_str!("../data/logo.svg"); HttpResponse::Ok() |