diff --git a/src/dav/mod.rs b/src/dav/mod.rs index 6ac25d9..02712ac 100644 --- a/src/dav/mod.rs +++ b/src/dav/mod.rs @@ -9,7 +9,7 @@ use self::path::*; use self::types::*; use self::util::*; use self::xml::*; -use crate::consts::{CSS_CONTENT_TYPE, DAV_XML_CONTENT_TYPE, HTML_CONTENT_TYPE}; +use crate::consts::{DAV_XML_CONTENT_TYPE, HTML_CONTENT_TYPE}; use crate::dandi::*; use axum::{ body::Body, @@ -19,6 +19,7 @@ use axum::{ RequestExt, }; use futures_util::TryStreamExt; +use std::convert::Infallible; use thiserror::Error; const WEBDAV_RESPONSE_HEADERS: [(&str, &str); 2] = [ @@ -27,8 +28,6 @@ const WEBDAV_RESPONSE_HEADERS: [(&str, &str); 2] = [ ("DAV", "1, 3"), ]; -static STYLESHEET: &str = include_str!("static/styles.css"); - pub(crate) struct DandiDav { client: Client, templater: Templater, @@ -47,35 +46,35 @@ impl DandiDav { pub(crate) async fn handle_request( &self, req: Request, - ) -> Result, DavError> { + ) -> Result, Infallible> { + let resp = self.inner_handle_request(req).await; + Ok((WEBDAV_RESPONSE_HEADERS, resp).into_response()) + } + + async fn inner_handle_request(&self, req: Request) -> Result, DavError> { let uri_path = req.uri().path(); // Performing this assignment outside the `match` magically makes this // compile on pre-1.74 Rusts: let m = req.method(); - let resp = match m { - &Method::GET if uri_path == "/.static/styles.css" => { - // Don't add WebDAV headers - return Ok(([(CONTENT_TYPE, CSS_CONTENT_TYPE)], STYLESHEET).into_response()); - } + match m { &Method::GET => { let Some(path) = DavPath::parse_uri_path(uri_path) else { return Ok(not_found()); }; - self.get(&path, uri_path).await? + self.get(&path, uri_path).await } - &Method::OPTIONS => StatusCode::NO_CONTENT.into_response(), + &Method::OPTIONS => Ok(StatusCode::NO_CONTENT.into_response()), m if m.as_str().eq_ignore_ascii_case("PROPFIND") => { let Some(path) = DavPath::parse_uri_path(uri_path) else { return Ok(not_found()); }; match req.extract::<(FiniteDepth, PropFind), _>().await { - Ok((depth, pf)) => self.propfind(&path, depth, pf).await?, - Err(r) => r, + Ok((depth, pf)) => self.propfind(&path, depth, pf).await, + Err(r) => Ok(r), } } - _ => StatusCode::METHOD_NOT_ALLOWED.into_response(), - }; - Ok((WEBDAV_RESPONSE_HEADERS, resp).into_response()) + _ => Ok(StatusCode::METHOD_NOT_ALLOWED.into_response()), + } } async fn get(&self, path: &DavPath, uri_path: &str) -> Result, DavError> { @@ -363,5 +362,5 @@ impl IntoResponse for DavError { } fn not_found() -> Response { - (StatusCode::NOT_FOUND, WEBDAV_RESPONSE_HEADERS, "404\n").into_response() + (StatusCode::NOT_FOUND, "404\n").into_response() } diff --git a/src/main.rs b/src/main.rs index 68bfa31..3beb24b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,26 +3,27 @@ mod dandi; mod dav; mod paths; mod s3; -use crate::consts::DEFAULT_API_URL; +use crate::consts::{CSS_CONTENT_TYPE, DEFAULT_API_URL}; use crate::dandi::Client; use crate::dav::{DandiDav, Templater}; use anyhow::Context; use axum::{ body::Body, extract::Request, - http::{response::Response, Method}, + http::{header::CONTENT_TYPE, response::Response, Method}, middleware::{self, Next}, - response::IntoResponse, + routing::get, Router, }; use clap::Parser; -use std::convert::Infallible; use std::net::IpAddr; use std::sync::Arc; use tower::service_fn; use tower_http::trace::TraceLayer; use tracing_subscriber::filter::LevelFilter; +static STYLESHEET: &str = include_str!("dav/static/styles.css"); + /// WebDAV view to DANDI Archive /// /// See for more information. @@ -56,11 +57,19 @@ async fn main() -> anyhow::Result<()> { let templater = Templater::load()?; let dav = Arc::new(DandiDav::new(client, templater, args.title)); let app = Router::new() + .route( + "/.static/styles.css", + get(|| async { + // Note: This response should not have WebDAV headers (DAV, Allow) + ([(CONTENT_TYPE, CSS_CONTENT_TYPE)], STYLESHEET) + }), + ) .nest_service( "/", service_fn(move |req: Request| { let dav = Arc::clone(&dav); - async move { Ok::<_, Infallible>(dav.handle_request(req).await.into_response()) } + // Box the large future: + async move { Box::pin(dav.handle_request(req)).await } }), ) .layer(middleware::from_fn(handle_head))