aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
authorSven-Hendrik Haase <svenstaro@gmail.com>2025-02-07 12:48:50 +0000
committerGitHub <noreply@github.com>2025-02-07 12:48:50 +0000
commit77b1c1cd0bfab5d4dc5e0994050fabd4a19cdd0f (patch)
tree0b9e157598d2361397ee09e7f196938d284c48f9 /src/main.rs
parentchore: clean up (diff)
parentAdd CHANGELOG entry for #1473 (diff)
downloadminiserve-77b1c1cd0bfab5d4dc5e0994050fabd4a19cdd0f.tar.gz
miniserve-77b1c1cd0bfab5d4dc5e0994050fabd4a19cdd0f.zip
Merge branch 'master' into upload-progress-bar
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs56
1 files changed, 51 insertions, 5 deletions
diff --git a/src/main.rs b/src/main.rs
index aa40585..ccf611c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,13 +6,18 @@ use std::time::Duration;
use actix_files::NamedFile;
use actix_web::{
dev::{fn_service, ServiceRequest, ServiceResponse},
- http::header::ContentType,
+ guard,
+ http::{header::ContentType, Method},
middleware, web, App, HttpRequest, HttpResponse, Responder,
};
use actix_web_httpauth::middleware::HttpAuthentication;
use anyhow::Result;
use clap::{crate_version, CommandFactory, Parser};
use colored::*;
+use dav_server::{
+ actix::{DavRequest, DavResponse},
+ DavConfig, DavHandler, DavMethodSet,
+};
use fast_qr::QRBuilder;
use log::{error, warn};
@@ -27,9 +32,11 @@ mod file_utils;
mod listing;
mod pipe;
mod renderer;
+mod webdav_fs;
use crate::config::MiniserveConfig;
use crate::errors::{RuntimeError, StartupError};
+use crate::webdav_fs::RestrictedFs;
static STYLESHEET: &str = grass::include!("data/style.scss");
@@ -52,9 +59,8 @@ fn main() -> Result<()> {
let miniserve_config = MiniserveConfig::try_from_args(args)?;
- run(miniserve_config).map_err(|e| {
+ run(miniserve_config).inspect_err(|e| {
errors::log_error_chain(e.to_string());
- e
})?;
Ok(())
@@ -89,6 +95,12 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), StartupError> {
));
}
+ if miniserve_config.webdav_enabled && miniserve_config.path.is_file() {
+ return Err(StartupError::WebdavWithFileServePath(
+ miniserve_config.path.to_string_lossy().to_string(),
+ ));
+ }
+
let inside_config = miniserve_config.clone();
let canon_path = miniserve_config
@@ -228,7 +240,7 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), StartupError> {
#[cfg(feature = "tls")]
let srv = match &miniserve_config.tls_rustls_config {
- Some(tls_config) => srv.listen_rustls(listener, tls_config.clone()),
+ Some(tls_config) => srv.listen_rustls_0_23(listener, tls_config.clone()),
None => srv.listen(listener),
};
@@ -308,7 +320,9 @@ fn configure_header(conf: &MiniserveConfig) -> middleware::DefaultHeaders {
/// This is where we configure the app to serve an index file, the file listing, or a single file.
fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
let dir_service = || {
- let mut files = actix_files::Files::new("", &conf.path);
+ // use routing guard so propfind and options requests fall through to the webdav handler
+ let mut files = actix_files::Files::new("", &conf.path)
+ .guard(guard::Any(guard::Get()).or(guard::Head()));
// Use specific index file if one was provided.
if let Some(ref index_file) = conf.index {
@@ -377,6 +391,38 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) {
// Handle directories
app.service(dir_service());
}
+
+ if conf.webdav_enabled {
+ let fs = RestrictedFs::new(&conf.path, conf.show_hidden);
+
+ let dav_server = DavHandler::builder()
+ .filesystem(fs)
+ .methods(DavMethodSet::WEBDAV_RO)
+ .hide_symlinks(conf.no_symlinks)
+ .strip_prefix(conf.route_prefix.to_owned())
+ .build_handler();
+
+ app.app_data(web::Data::new(dav_server.clone()));
+
+ app.service(
+ // actix requires tail segment to be named, even if unused
+ web::resource("/{tail}*")
+ .guard(
+ guard::Any(guard::Options())
+ .or(guard::Method(Method::from_bytes(b"PROPFIND").unwrap())),
+ )
+ .to(dav_handler),
+ );
+ }
+}
+
+async fn dav_handler(req: DavRequest, davhandler: web::Data<DavHandler>) -> DavResponse {
+ if let Some(prefix) = req.prefix() {
+ let config = DavConfig::new().strip_prefix(prefix);
+ davhandler.handle_with(config, req.request).await.into()
+ } else {
+ davhandler.handle(req.request).await.into()
+ }
}
async fn error_404(req: HttpRequest) -> Result<HttpResponse, RuntimeError> {