From 1fb0c2aafa99f0d236ca07810264e66b8b020a07 Mon Sep 17 00:00:00 2001
From: _ <_@_>
Date: Sat, 31 Oct 2020 09:35:18 -0500
Subject: [PATCH] :lipstick: Switched to a handlebars template for the whole
dir index
---
ptth_handlebars/file_server_dir.html | 1 +
src/bin/file_server.rs | 7 +-
src/server/file_server.rs | 137 +++++++++++++--------------
3 files changed, 74 insertions(+), 71 deletions(-)
diff --git a/ptth_handlebars/file_server_dir.html b/ptth_handlebars/file_server_dir.html
index 7563912..cc75253 100644
--- a/ptth_handlebars/file_server_dir.html
+++ b/ptth_handlebars/file_server_dir.html
@@ -1,4 +1,5 @@
+- ..
{{#each entries}}
-
diff --git a/src/bin/file_server.rs b/src/bin/file_server.rs
index 356fa7c..1e608c6 100644
--- a/src/bin/file_server.rs
+++ b/src/bin/file_server.rs
@@ -92,7 +92,12 @@ async fn main () -> Result <(), Box > {
let mut handlebars = handlebars::Handlebars::new ();
- handlebars.register_template_file ("file_server_dir_entry", "ptth_handlebars/file_server_dir_entry.html")?;
+ for (k, v) in vec! [
+ ("file_server_dir_entry", "ptth_handlebars/file_server_dir_entry.html"),
+ ("file_server_dir", "ptth_handlebars/file_server_dir.html"),
+ ].into_iter () {
+ handlebars.register_template_file (k, v)?;
+ }
let handlebars = Arc::new (handlebars);
diff --git a/src/server/file_server.rs b/src/server/file_server.rs
index 4f4fd9f..7c9b9fd 100644
--- a/src/server/file_server.rs
+++ b/src/server/file_server.rs
@@ -47,83 +47,80 @@ fn parse_range_header (range_str: &str) -> (Option , Option ) {
(start, end)
}
+use serde::Serialize;
+use tokio::fs::DirEntry;
+
+// This could probably be done with borrows, if I owned the
+// tokio::fs::DirEntry instead of consuming it
+
+#[derive (Serialize)]
+struct TemplateDirEntry {
+ trailing_slash: &'static str,
+ file_name: String,
+ encoded_file_name: String,
+ error: bool,
+}
+
+async fn read_dir_entry (entry: DirEntry) -> TemplateDirEntry
+{
+ let trailing_slash = match entry.file_type ().await {
+ Ok (t) => if t.is_dir () {
+ "/"
+ }
+ else {
+ ""
+ },
+ Err (_) => "",
+ };
+
+ let file_name = match entry.file_name ().into_string () {
+ Ok (x) => x,
+ Err (_) => return TemplateDirEntry {
+ trailing_slash: "",
+ file_name: "".into (),
+ encoded_file_name: "".into (),
+ error: true,
+ },
+ };
+
+ use percent_encoding::*;
+
+ let encoded_file_name = utf8_percent_encode (&file_name, CONTROLS).to_string ();
+
+ TemplateDirEntry {
+ trailing_slash: &trailing_slash,
+ file_name,
+ encoded_file_name,
+ error: false,
+ }
+}
+
async fn serve_dir (
handlebars: Arc >,
mut dir: ReadDir
-) -> http_serde::Response {
- let (tx, rx) = channel (2);
+) -> http_serde::Response
+{
+ let mut entries = vec! [];
- let handlebars = handlebars.clone ();
- tokio::spawn (async move {
- let mut tx = tx;
-
- tx.send (Ok::<_, Infallible> (String::from ("
").into_bytes ())).await.unwrap ();
-
- let handlebars = handlebars.clone ();
- while let Ok (entry) = dir.next_entry ().await {
- let handlebars = handlebars.clone ();
- let entry: tokio::fs::DirEntry = match entry {
- Some (x) => x,
- None => break,
- };
-
- let trailing_slash = match entry.file_type ().await {
- Ok (t) => if t.is_dir () {
- "/"
- }
- else {
- ""
- },
- Err (_) => "",
- };
-
- let file_name = match entry.file_name ().into_string () {
- Ok (x) => x,
- Err (_) => {
- let s = format! ("- (file_name error)
\n");
- if tx.send (Ok::<_, Infallible> (s.into_bytes ())).await.is_err ()
- {
- break;
- }
- continue;
- }
- };
-
- use std::borrow::Cow;
- use percent_encoding::*;
-
- let encoded_file_name: Cow = utf8_percent_encode (&file_name, CONTROLS).into ();
-
- #[derive (serde::Serialize)]
- struct TemplateDirEntry <'a> {
- trailing_slash: &'a str,
- file_name: &'a str,
- encoded_file_name: Cow <'a, str>,
- }
-
- let s = handlebars.render (
- "file_server_dir_entry",
- &TemplateDirEntry {
- trailing_slash: &trailing_slash,
- file_name: &file_name,
- encoded_file_name,
- }).unwrap ();
-
- if tx.send (Ok::<_, Infallible> (s.into_bytes ())).await.is_err ()
- {
- break;
- }
- }
-
- tx.send (Ok::<_, Infallible> (String::from ("
").into_bytes ())).await.unwrap ();
- });
+ while let Ok (Some (entry)) = dir.next_entry ().await {
+ entries.push (read_dir_entry (entry).await);
+ }
- let mut response = http_serde::Response::default ();
+ #[derive (Serialize)]
+ struct TemplateDirPage {
+ entries: Vec ,
+ }
- response.header ("content-type".into (), String::from ("text/html").into_bytes ());
- response.body (rx);
+ let s = handlebars.render ("file_server_dir", &TemplateDirPage {
+ entries,
+ }).unwrap ();
- response
+ let mut resp = http_serde::Response::default ();
+ resp
+ .header ("content-type".to_string (), "text/html".to_string ().into_bytes ())
+ .body_bytes (s.into_bytes ())
+ ;
+ resp
}
async fn serve_file (