Skip to content

Commit

Permalink
Merge pull request #42 from dandi/route-styles
Browse files Browse the repository at this point in the history
Handle requests for `/.static/styles.css` via top-level router
  • Loading branch information
jwodder authored Jan 31, 2024
2 parents 99ebe47 + 663e16c commit 878dc4c
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 22 deletions.
33 changes: 16 additions & 17 deletions src/dav/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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] = [
Expand All @@ -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,
Expand All @@ -47,35 +46,35 @@ impl DandiDav {
pub(crate) async fn handle_request(
&self,
req: Request<Body>,
) -> Result<Response<Body>, DavError> {
) -> Result<Response<Body>, Infallible> {
let resp = self.inner_handle_request(req).await;
Ok((WEBDAV_RESPONSE_HEADERS, resp).into_response())
}

async fn inner_handle_request(&self, req: Request<Body>) -> Result<Response<Body>, 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<Response<Body>, DavError> {
Expand Down Expand Up @@ -363,5 +362,5 @@ impl IntoResponse for DavError {
}

fn not_found() -> Response<Body> {
(StatusCode::NOT_FOUND, WEBDAV_RESPONSE_HEADERS, "404\n").into_response()
(StatusCode::NOT_FOUND, "404\n").into_response()
}
19 changes: 14 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/dandi/dandidav> for more information.
Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit 878dc4c

Please sign in to comment.